@@ -49,7 +49,9 @@ use rustc_middle::ty::{
4949use rustc_middle:: { bug, span_bug} ;
5050use rustc_session:: lint;
5151use rustc_span:: { BytePos , Pos , Span , Symbol , sym} ;
52+ use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt as _;
5253use rustc_trait_selection:: infer:: InferCtxtExt ;
54+ use rustc_trait_selection:: solve;
5355use tracing:: { debug, instrument} ;
5456
5557use super :: FnCtxt ;
@@ -196,17 +198,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
196198 let closure_def_id = closure_def_id. expect_local ( ) ;
197199
198200 assert_eq ! ( self . tcx. hir_body_owner_def_id( body. id( ) ) , closure_def_id) ;
201+
202+ let closure_fcx = FnCtxt :: new ( self , self . tcx . param_env ( closure_def_id) , closure_def_id) ;
203+
199204 let mut delegate = InferBorrowKind {
205+ fcx : & closure_fcx,
200206 closure_def_id,
201207 capture_information : Default :: default ( ) ,
202208 fake_reads : Default :: default ( ) ,
203209 } ;
204210
205- let _ = euv:: ExprUseVisitor :: new (
206- & FnCtxt :: new ( self , self . tcx . param_env ( closure_def_id) , closure_def_id) ,
207- & mut delegate,
208- )
209- . consume_body ( body) ;
211+ let _ = euv:: ExprUseVisitor :: new ( & closure_fcx, & mut delegate) . consume_body ( body) ;
210212
211213 // There are several curious situations with coroutine-closures where
212214 // analysis is too aggressive with borrows when the coroutine-closure is
@@ -286,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
286288 let hir:: def:: Res :: Local ( local_id) = path. res else {
287289 bug ! ( ) ;
288290 } ;
289- let place = self . place_for_root_variable ( closure_def_id, local_id) ;
291+ let place = closure_fcx . place_for_root_variable ( closure_def_id, local_id) ;
290292 delegate. capture_information . push ( (
291293 place,
292294 ty:: CaptureInfo {
@@ -325,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
325327
326328 if let Some ( upvars) = self . tcx . upvars_mentioned ( closure_def_id) {
327329 for var_hir_id in upvars. keys ( ) {
328- let place = self . place_for_root_variable ( closure_def_id, * var_hir_id) ;
330+ let place = closure_fcx . place_for_root_variable ( closure_def_id, * var_hir_id) ;
329331
330332 debug ! ( "seed place {:?}" , place) ;
331333
@@ -559,17 +561,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
559561 bug ! ( ) ;
560562 } ;
561563
564+ let coroutine_fcx =
565+ FnCtxt :: new ( self , self . tcx . param_env ( coroutine_def_id) , coroutine_def_id) ;
566+
562567 let mut delegate = InferBorrowKind {
568+ fcx : & coroutine_fcx,
563569 closure_def_id : coroutine_def_id,
564570 capture_information : Default :: default ( ) ,
565571 fake_reads : Default :: default ( ) ,
566572 } ;
567573
568- let _ = euv:: ExprUseVisitor :: new (
569- & FnCtxt :: new ( self , self . tcx . param_env ( coroutine_def_id) , coroutine_def_id) ,
570- & mut delegate,
571- )
572- . consume_expr ( body) ;
574+ let _ = euv:: ExprUseVisitor :: new ( & coroutine_fcx, & mut delegate) . consume_expr ( body) ;
573575
574576 let ( _, kind, _) = self . process_collected_capture_information (
575577 hir:: CaptureBy :: Ref ,
@@ -1125,6 +1127,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11251127 ) ;
11261128 }
11271129 }
1130+ fn normalize_capture_place ( & self , span : Span , place : Place < ' tcx > ) -> Place < ' tcx > {
1131+ let mut place = self . resolve_vars_if_possible ( place) ;
1132+
1133+ // In the new solver, types in HIR `Place`s can contain unnormalized aliases,
1134+ // which can ICE later (e.g. when projecting fields for diagnostics).
1135+ if self . next_trait_solver ( ) {
1136+ let cause = self . misc ( span) ;
1137+ let at = self . at ( & cause, self . param_env ) ;
1138+ match solve:: deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals (
1139+ at,
1140+ place. clone ( ) ,
1141+ vec ! [ ] ,
1142+ ) {
1143+ Ok ( ( normalized, goals) ) => {
1144+ if !goals. is_empty ( ) {
1145+ let mut typeck_results = self . typeck_results . borrow_mut ( ) ;
1146+ typeck_results. coroutine_stalled_predicates . extend (
1147+ goals
1148+ . into_iter ( )
1149+ // FIXME: throwing away the param-env :(
1150+ . map ( |goal| ( goal. predicate , self . misc ( span) ) ) ,
1151+ ) ;
1152+ }
1153+ normalized
1154+ }
1155+ Err ( errors) => {
1156+ let guar = self . infcx . err_ctxt ( ) . report_fulfillment_errors ( errors) ;
1157+ place. base_ty = Ty :: new_error ( self . tcx , guar) ;
1158+ for proj in & mut place. projections {
1159+ proj. ty = Ty :: new_error ( self . tcx , guar) ;
1160+ }
1161+ place
1162+ }
1163+ }
1164+ } else {
1165+ // For the old solver we can rely on `normalize` to eagerly normalize aliases.
1166+ self . normalize ( span, place)
1167+ }
1168+ }
11281169
11291170 /// Combines all the reasons for 2229 migrations
11301171 fn compute_2229_migrations_reasons (
@@ -1734,11 +1775,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17341775 ) -> Place < ' tcx > {
17351776 let upvar_id = ty:: UpvarId :: new ( var_hir_id, closure_def_id) ;
17361777
1737- Place {
1778+ let place = Place {
17381779 base_ty : self . node_ty ( var_hir_id) ,
17391780 base : PlaceBase :: Upvar ( upvar_id) ,
17401781 projections : Default :: default ( ) ,
1741- }
1782+ } ;
1783+
1784+ // Normalize eagerly when inserting into `capture_information`, so all downstream
1785+ // capture analysis can assume a normalized `Place`.
1786+ self . normalize_capture_place ( self . tcx . hir_span ( var_hir_id) , place)
17421787 }
17431788
17441789 fn should_log_capture_analysis ( & self , closure_def_id : LocalDefId ) -> bool {
@@ -1994,7 +2039,8 @@ fn drop_location_span(tcx: TyCtxt<'_>, hir_id: HirId) -> Span {
19942039 tcx. sess . source_map ( ) . end_point ( owner_span)
19952040}
19962041
1997- struct InferBorrowKind < ' tcx > {
2042+ struct InferBorrowKind < ' fcx , ' a , ' tcx > {
2043+ fcx : & ' fcx FnCtxt < ' a , ' tcx > ,
19982044 // The def-id of the closure whose kind and upvar accesses are being inferred.
19992045 closure_def_id : LocalDefId ,
20002046
@@ -2028,7 +2074,7 @@ struct InferBorrowKind<'tcx> {
20282074 fake_reads : Vec < ( Place < ' tcx > , FakeReadCause , HirId ) > ,
20292075}
20302076
2031- impl < ' tcx > euv:: Delegate < ' tcx > for InferBorrowKind < ' tcx > {
2077+ impl < ' fcx , ' a , ' tcx > euv:: Delegate < ' tcx > for InferBorrowKind < ' fcx , ' a , ' tcx > {
20322078 #[ instrument( skip( self ) , level = "debug" ) ]
20332079 fn fake_read (
20342080 & mut self ,
@@ -2042,8 +2088,10 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
20422088 // such as deref of a raw pointer.
20432089 let dummy_capture_kind = ty:: UpvarCapture :: ByRef ( ty:: BorrowKind :: Immutable ) ;
20442090
2045- let ( place, _) =
2046- restrict_capture_precision ( place_with_id. place . clone ( ) , dummy_capture_kind) ;
2091+ let span = self . fcx . tcx . hir_span ( diag_expr_id) ;
2092+ let place = self . fcx . normalize_capture_place ( span, place_with_id. place . clone ( ) ) ;
2093+
2094+ let ( place, _) = restrict_capture_precision ( place, dummy_capture_kind) ;
20472095
20482096 let ( place, _) = restrict_repr_packed_field_ref_capture ( place, dummy_capture_kind) ;
20492097 self . fake_reads . push ( ( place, cause, diag_expr_id) ) ;
@@ -2054,8 +2102,11 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
20542102 let PlaceBase :: Upvar ( upvar_id) = place_with_id. place . base else { return } ;
20552103 assert_eq ! ( self . closure_def_id, upvar_id. closure_expr_id) ;
20562104
2105+ let span = self . fcx . tcx . hir_span ( diag_expr_id) ;
2106+ let place = self . fcx . normalize_capture_place ( span, place_with_id. place . clone ( ) ) ;
2107+
20572108 self . capture_information . push ( (
2058- place_with_id . place . clone ( ) ,
2109+ place,
20592110 ty:: CaptureInfo {
20602111 capture_kind_expr_id : Some ( diag_expr_id) ,
20612112 path_expr_id : Some ( diag_expr_id) ,
@@ -2069,8 +2120,11 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
20692120 let PlaceBase :: Upvar ( upvar_id) = place_with_id. place . base else { return } ;
20702121 assert_eq ! ( self . closure_def_id, upvar_id. closure_expr_id) ;
20712122
2123+ let span = self . fcx . tcx . hir_span ( diag_expr_id) ;
2124+ let place = self . fcx . normalize_capture_place ( span, place_with_id. place . clone ( ) ) ;
2125+
20722126 self . capture_information . push ( (
2073- place_with_id . place . clone ( ) ,
2127+ place,
20742128 ty:: CaptureInfo {
20752129 capture_kind_expr_id : Some ( diag_expr_id) ,
20762130 path_expr_id : Some ( diag_expr_id) ,
@@ -2092,14 +2146,16 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
20922146 // The region here will get discarded/ignored
20932147 let capture_kind = ty:: UpvarCapture :: ByRef ( bk) ;
20942148
2149+ let span = self . fcx . tcx . hir_span ( diag_expr_id) ;
2150+ let place = self . fcx . normalize_capture_place ( span, place_with_id. place . clone ( ) ) ;
2151+
20952152 // We only want repr packed restriction to be applied to reading references into a packed
20962153 // struct, and not when the data is being moved. Therefore we call this method here instead
20972154 // of in `restrict_capture_precision`.
2098- let ( place, mut capture_kind) =
2099- restrict_repr_packed_field_ref_capture ( place_with_id. place . clone ( ) , capture_kind) ;
2155+ let ( place, mut capture_kind) = restrict_repr_packed_field_ref_capture ( place, capture_kind) ;
21002156
21012157 // Raw pointers don't inherit mutability
2102- if place_with_id . place . deref_tys ( ) . any ( Ty :: is_raw_ptr) {
2158+ if place. deref_tys ( ) . any ( Ty :: is_raw_ptr) {
21032159 capture_kind = ty:: UpvarCapture :: ByRef ( ty:: BorrowKind :: Immutable ) ;
21042160 }
21052161
0 commit comments