Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/closure/analysis.rs')
| -rw-r--r-- | crates/hir-ty/src/infer/closure/analysis.rs | 62 |
1 files changed, 32 insertions, 30 deletions
diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs index 668d7496cd..5ea43bc03c 100644 --- a/crates/hir-ty/src/infer/closure/analysis.rs +++ b/crates/hir-ty/src/infer/closure/analysis.rs @@ -41,10 +41,11 @@ use hir_def::{ resolver::ValueNs, }; use macros::{TypeFoldable, TypeVisitable}; +use rustc_abi::ExternAbi; use rustc_ast_ir::Mutability; use rustc_hash::{FxBuildHasher, FxHashMap}; use rustc_type_ir::{ - BoundVar, ClosureKind, TypeVisitableExt as _, + BoundVar, ClosureKind, inherent::{AdtDef as _, GenericArgs as _, IntoKind as _, Ty as _}, }; use smallvec::{SmallVec, smallvec}; @@ -52,7 +53,7 @@ use span::Edition; use tracing::{debug, instrument}; use crate::{ - FnAbi, + Span, infer::{ CaptureInfo, CaptureSourceStack, CapturedPlace, InferenceContext, UpvarCapture, closure::analysis::expr_use_visitor::{ @@ -195,7 +196,7 @@ type InferredCaptureInformation = Vec<(Place, CaptureInfo)>; impl<'a, 'db> InferenceContext<'a, 'db> { pub(crate) fn closure_analyze(&mut self) { - let upvars = crate::upvars::upvars_mentioned(self.db, self.owner) + let upvars = crate::upvars::upvars_mentioned(self.db, self.store_owner) .unwrap_or(const { &FxHashMap::with_hasher(FxBuildHasher) }); for root_expr in self.store.expr_roots() { self.analyze_closures_in_expr(root_expr, upvars); @@ -284,7 +285,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // coroutine-closures that are `move` since otherwise they themselves will // be borrowing from the outer environment, so there's no self-borrows occurring. if let UpvarArgs::Coroutine(..) = args - && let hir_def::hir::ClosureKind::AsyncBlock { source: CoroutineSource::Closure } = + && let hir_def::hir::ClosureKind::Coroutine { source: CoroutineSource::Closure, .. } = closure_kind && let parent_hir_id = ExpressionStore::closure_for_coroutine(closure_expr_id) && let parent_ty = self.result.expr_ty(parent_hir_id) @@ -310,8 +311,9 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // // FIXME(async_closures): This could be cleaned up. It's a bit janky that we're just // moving all of the `LocalSource::AsyncFn` locals here. - if let hir_def::hir::ClosureKind::AsyncBlock { + if let hir_def::hir::ClosureKind::Coroutine { source: CoroutineSource::Fn | CoroutineSource::Closure, + .. } = closure_kind { let Expr::Block { statements, .. } = &self.store[body] else { @@ -328,7 +330,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> { let Expr::Path(path) = &self.store[init] else { panic!(); }; - let update_guard = self.resolver.update_to_inner_scope(self.db, self.owner, init); + let update_guard = + self.resolver.update_to_inner_scope(self.db, self.store_owner, init); let Some(ValueNs::LocalBinding(local_id)) = self.resolver.resolve_path_in_value_ns_fully( self.db, @@ -402,9 +405,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // For coroutine-closures, we additionally must compute the // `coroutine_captures_by_ref_ty` type, which is used to generate the by-ref // version of the coroutine-closure's output coroutine. - if let UpvarArgs::CoroutineClosure(args) = args - && !args.references_error() - { + if let UpvarArgs::CoroutineClosure(args) = args { let closure_env_region: Region<'_> = Region::new_bound( self.interner(), rustc_type_ir::INNERMOST, @@ -459,7 +460,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { tupled_upvars_ty_for_borrow, false, Safety::Safe, - FnAbi::Rust, + ExternAbi::Rust, ), self.types.coroutine_captures_by_ref_bound_var_kinds, ), @@ -506,7 +507,11 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // Build a tuple (U0..Un) of the final upvar types U0..Un // and unify the upvar tuple type in the closure with it: let final_tupled_upvars_type = Ty::new_tup(self.interner(), &final_upvar_tys); - self.demand_suptype(args.tupled_upvars_ty(), final_tupled_upvars_type); + _ = self.demand_suptype( + closure_expr_id.into(), + args.tupled_upvars_ty(), + final_tupled_upvars_type, + ); let fake_reads = delegate.fake_reads; @@ -737,7 +742,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { }; let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else { - let mutability = self.determine_capture_mutability(&place); + let mutability = self.determine_capture_mutability(closure_def_id, &place); let min_cap_list = vec![CapturedPlace { place, info: capture_info, mutability }]; root_var_min_capture_list.insert(var_hir_id, min_cap_list); continue; @@ -846,7 +851,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // Only need to insert when we don't have an ancestor in the existing min capture list if !ancestor_found { - let mutability = self.determine_capture_mutability(&place); + let mutability = self.determine_capture_mutability(closure_def_id, &place); let captured_place = CapturedPlace { place, info: updated_capture_info, mutability }; min_cap_list.push(captured_place); @@ -915,12 +920,12 @@ impl<'a, 'db> InferenceContext<'a, 'db> { self.result.closures_data.insert(closure_def_id, closure_data); } - fn normalize_capture_place(&self, place: Place) -> Place { - let mut place = self.infcx().resolve_vars_if_possible(place); + fn normalize_capture_place(&mut self, span: Span, place: Place) -> Place { + let place = self.infcx().resolve_vars_if_possible(place); // In the new solver, types in HIR `Place`s can contain unnormalized aliases, // which can ICE later (e.g. when projecting fields for diagnostics). - let cause = ObligationCause::misc(); + let cause = ObligationCause::new(span); let at = self.table.at(&cause); match normalize::deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals( at, @@ -940,11 +945,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> { } normalized } - Err(_errors) => { - place.base_ty = self.types.types.error.store(); - for proj in &mut place.projections { - proj.ty = self.types.types.error.store(); - } + Err(errors) => { + self.table.trait_errors.extend(errors); place } } @@ -997,7 +999,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { } } - fn place_for_root_variable(&self, closure_def_id: ExprId, var_hir_id: BindingId) -> Place { + fn place_for_root_variable(&mut self, closure_def_id: ExprId, var_hir_id: BindingId) -> Place { let place = Place { base_ty: self.result.binding_ty(var_hir_id).store(), base: PlaceBase::Upvar { closure: closure_def_id, var_id: var_hir_id }, @@ -1006,13 +1008,13 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // Normalize eagerly when inserting into `capture_information`, so all downstream // capture analysis can assume a normalized `Place`. - self.normalize_capture_place(place) + self.normalize_capture_place(var_hir_id.into(), place) } /// A captured place is mutable if /// 1. Projections don't include a Deref of an immut-borrow, **and** /// 2. PlaceBase is mut or projections include a Deref of a mut-borrow. - fn determine_capture_mutability(&mut self, place: &Place) -> Mutability { + fn determine_capture_mutability(&mut self, closure_expr: ExprId, place: &Place) -> Mutability { let var_hir_id = match place.base { PlaceBase::Upvar { var_id, .. } => var_id, _ => unreachable!(), @@ -1025,7 +1027,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { }; for pointer_ty in place.deref_tys() { - match self.table.structurally_resolve_type(pointer_ty).kind() { + match self.structurally_resolve_type(closure_expr.into(), pointer_ty).kind() { // We don't capture derefs of raw ptrs TyKind::RawPtr(_, _) => unreachable!(), @@ -1127,7 +1129,7 @@ fn restrict_repr_packed_field_ref_capture( // Return true for fields of packed structs. match p.kind { ProjectionKind::Field { .. } => match ty.kind() { - TyKind::Adt(def, _) if def.repr().packed() => { + TyKind::Adt(def, _) if def.is_packed() => { // We stop here regardless of field alignment. Field alignment can change as // types change, including the types of private fields in other crates, and that // shouldn't affect how we compute our captures. @@ -1210,7 +1212,7 @@ impl<'db> euv::Delegate<'db> for InferBorrowKind { let mut dummy_capture_info = CaptureInfo { sources: SmallVec::new(), capture_kind: dummy_capture_kind }; - let place = ctx.normalize_capture_place(place_with_id.place.clone()); + let place = ctx.normalize_capture_place(place_with_id.span(), place_with_id.place.clone()); let place = restrict_capture_precision(place, &mut dummy_capture_info); @@ -1226,7 +1228,7 @@ impl<'db> euv::Delegate<'db> for InferBorrowKind { }; assert_eq!(self.closure_def_id, upvar_closure); - let place = ctx.normalize_capture_place(place_with_id.place.clone()); + let place = ctx.normalize_capture_place(place_with_id.span(), place_with_id.place.clone()); self.capture_information.push(( place, @@ -1241,7 +1243,7 @@ impl<'db> euv::Delegate<'db> for InferBorrowKind { }; assert_eq!(self.closure_def_id, upvar_closure); - let place = ctx.normalize_capture_place(place_with_id.place.clone()); + let place = ctx.normalize_capture_place(place_with_id.span(), place_with_id.place.clone()); self.capture_information.push(( place, @@ -1266,7 +1268,7 @@ impl<'db> euv::Delegate<'db> for InferBorrowKind { let mut capture_info = CaptureInfo { sources: place_with_id.origins.iter().cloned().collect(), capture_kind }; - let place = ctx.normalize_capture_place(place_with_id.place.clone()); + let place = ctx.normalize_capture_place(place_with_id.span(), place_with_id.place.clone()); // We only want repr packed restriction to be applied to reading references into a packed // struct, and not when the data is being moved. Therefore we call this method here instead |