@@ -5,7 +5,7 @@ use std::iter;
55use  hir:: def_id:: { DefId ,  DefIdMap ,  LocalDefId } ; 
66use  rustc_data_structures:: fx:: { FxHashSet ,  FxIndexMap ,  FxIndexSet } ; 
77use  rustc_errors:: codes:: * ; 
8- use  rustc_errors:: { Applicability ,  ErrorGuaranteed ,  pluralize,  struct_span_code_err} ; 
8+ use  rustc_errors:: { Applicability ,  ErrorGuaranteed ,  MultiSpan ,   pluralize,  struct_span_code_err} ; 
99use  rustc_hir:: def:: { DefKind ,  Res } ; 
1010use  rustc_hir:: intravisit:: VisitorExt ; 
1111use  rustc_hir:: { self  as  hir,  AmbigArg ,  GenericParamKind ,  ImplItemKind ,  intravisit} ; 
@@ -14,10 +14,10 @@ use rustc_infer::traits::util;
1414use  rustc_middle:: ty:: error:: { ExpectedFound ,  TypeError } ; 
1515use  rustc_middle:: ty:: { 
1616    self ,  BottomUpFolder ,  GenericArgs ,  GenericParamDefKind ,  Ty ,  TyCtxt ,  TypeFoldable ,  TypeFolder , 
17-     TypeSuperFoldable ,  TypeVisitableExt ,  TypingMode ,  Upcast , 
17+     TypeSuperFoldable ,  TypeVisitable ,   TypeVisitableExt ,   TypeVisitor ,  TypingMode ,  Upcast , 
1818} ; 
1919use  rustc_middle:: { bug,  span_bug} ; 
20- use  rustc_span:: Span ; 
20+ use  rustc_span:: { DUMMY_SP ,   Span } ; 
2121use  rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ; 
2222use  rustc_trait_selection:: infer:: InferCtxtExt ; 
2323use  rustc_trait_selection:: regions:: InferCtxtRegionExt ; 
@@ -1141,6 +1141,10 @@ fn check_region_bounds_on_impl_item<'tcx>(
11411141        return  Ok ( ( ) ) ; 
11421142    } 
11431143
1144+     if  !delay && let  Some ( guar)  = check_region_late_boundedness ( tcx,  impl_m,  trait_m)  { 
1145+         return  Err ( guar) ; 
1146+     } 
1147+ 
11441148    let  span = tcx
11451149        . hir_get_generics ( impl_m. def_id . expect_local ( ) ) 
11461150        . expect ( "expected impl item to have generics or else we can't compare them" ) 
@@ -1221,6 +1225,233 @@ fn check_region_bounds_on_impl_item<'tcx>(
12211225    Err ( reported) 
12221226} 
12231227
1228+ #[ allow( unused) ]  
1229+ enum  LateEarlyMismatch < ' tcx >  { 
1230+     EarlyInImpl ( DefId ,  DefId ,  ty:: Region < ' tcx > ) , 
1231+     LateInImpl ( DefId ,  DefId ,  ty:: Region < ' tcx > ) , 
1232+ } 
1233+ 
1234+ fn  check_region_late_boundedness < ' tcx > ( 
1235+     tcx :  TyCtxt < ' tcx > , 
1236+     impl_m :  ty:: AssocItem , 
1237+     trait_m :  ty:: AssocItem , 
1238+ )  -> Option < ErrorGuaranteed >  { 
1239+     if  !impl_m. is_fn ( )  { 
1240+         return  None ; 
1241+     } 
1242+ 
1243+     let  ( infcx,  param_env)  = tcx
1244+         . infer_ctxt ( ) 
1245+         . build_with_typing_env ( ty:: TypingEnv :: non_body_analysis ( tcx,  impl_m. def_id ) ) ; 
1246+ 
1247+     let  impl_m_args = infcx. fresh_args_for_item ( DUMMY_SP ,  impl_m. def_id ) ; 
1248+     let  impl_m_sig = tcx. fn_sig ( impl_m. def_id ) . instantiate ( tcx,  impl_m_args) ; 
1249+     let  impl_m_sig = tcx. liberate_late_bound_regions ( impl_m. def_id ,  impl_m_sig) ; 
1250+ 
1251+     let  trait_m_args = infcx. fresh_args_for_item ( DUMMY_SP ,  trait_m. def_id ) ; 
1252+     let  trait_m_sig = tcx. fn_sig ( trait_m. def_id ) . instantiate ( tcx,  trait_m_args) ; 
1253+     let  trait_m_sig = tcx. liberate_late_bound_regions ( impl_m. def_id ,  trait_m_sig) ; 
1254+ 
1255+     let  ocx = ObligationCtxt :: new ( & infcx) ; 
1256+ 
1257+     // Equate the signatures so that we can infer whether a late-bound param was present where 
1258+     // an early-bound param was expected, since we replace the late-bound lifetimes with 
1259+     // `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will 
1260+     // resolve to `ReLateParam` if there is a mismatch. 
1261+     let  Ok ( ( ) )  = ocx. eq ( 
1262+         & ObligationCause :: dummy ( ) , 
1263+         param_env, 
1264+         ty:: Binder :: dummy ( trait_m_sig) , 
1265+         ty:: Binder :: dummy ( impl_m_sig) , 
1266+     )  else  { 
1267+         return  None ; 
1268+     } ; 
1269+ 
1270+     let  errors = ocx. select_where_possible ( ) ; 
1271+     if  !errors. is_empty ( )  { 
1272+         return  None ; 
1273+     } 
1274+ 
1275+     let  mut  mismatched = vec ! [ ] ; 
1276+ 
1277+     let  impl_generics = tcx. generics_of ( impl_m. def_id ) ; 
1278+     for  ( id_arg,  arg)  in 
1279+         std:: iter:: zip ( ty:: GenericArgs :: identity_for_item ( tcx,  impl_m. def_id ) ,  impl_m_args) 
1280+     { 
1281+         if  let  ty:: GenericArgKind :: Lifetime ( r)  = arg. unpack ( ) 
1282+             && let  ty:: ReVar ( vid)  = r. kind ( ) 
1283+             && let  r = infcx
1284+                 . inner 
1285+                 . borrow_mut ( ) 
1286+                 . unwrap_region_constraints ( ) 
1287+                 . opportunistic_resolve_var ( tcx,  vid) 
1288+             && let  ty:: ReLateParam ( ty:: LateParamRegion  { 
1289+                 kind :  ty:: LateParamRegionKind :: Named ( trait_param_def_id,  _) , 
1290+                 ..
1291+             } )  = r. kind ( ) 
1292+             && let  ty:: ReEarlyParam ( ebr)  = id_arg. expect_region ( ) . kind ( ) 
1293+         { 
1294+             mismatched. push ( LateEarlyMismatch :: EarlyInImpl ( 
1295+                 impl_generics. region_param ( ebr,  tcx) . def_id , 
1296+                 trait_param_def_id, 
1297+                 id_arg. expect_region ( ) , 
1298+             ) ) ; 
1299+         } 
1300+     } 
1301+ 
1302+     let  trait_generics = tcx. generics_of ( trait_m. def_id ) ; 
1303+     for  ( id_arg,  arg)  in 
1304+         std:: iter:: zip ( ty:: GenericArgs :: identity_for_item ( tcx,  trait_m. def_id ) ,  trait_m_args) 
1305+     { 
1306+         if  let  ty:: GenericArgKind :: Lifetime ( r)  = arg. unpack ( ) 
1307+             && let  ty:: ReVar ( vid)  = r. kind ( ) 
1308+             && let  r = infcx
1309+                 . inner 
1310+                 . borrow_mut ( ) 
1311+                 . unwrap_region_constraints ( ) 
1312+                 . opportunistic_resolve_var ( tcx,  vid) 
1313+             && let  ty:: ReLateParam ( ty:: LateParamRegion  { 
1314+                 kind :  ty:: LateParamRegionKind :: Named ( impl_param_def_id,  _) , 
1315+                 ..
1316+             } )  = r. kind ( ) 
1317+             && let  ty:: ReEarlyParam ( ebr)  = id_arg. expect_region ( ) . kind ( ) 
1318+         { 
1319+             mismatched. push ( LateEarlyMismatch :: LateInImpl ( 
1320+                 impl_param_def_id, 
1321+                 trait_generics. region_param ( ebr,  tcx) . def_id , 
1322+                 id_arg. expect_region ( ) , 
1323+             ) ) ; 
1324+         } 
1325+     } 
1326+ 
1327+     if  mismatched. is_empty ( )  { 
1328+         return  None ; 
1329+     } 
1330+ 
1331+     let  spans:  Vec < _ >  = mismatched
1332+         . iter ( ) 
1333+         . map ( |param| { 
1334+             let  ( LateEarlyMismatch :: EarlyInImpl ( impl_param_def_id,  ..) 
1335+             | LateEarlyMismatch :: LateInImpl ( impl_param_def_id,  ..) )  = param; 
1336+             tcx. def_span ( impl_param_def_id) 
1337+         } ) 
1338+         . collect ( ) ; 
1339+ 
1340+     let  mut  diag = tcx
1341+         . dcx ( ) 
1342+         . struct_span_err ( spans,  "lifetime parameters do not match the trait definition" ) 
1343+         . with_note ( "lifetime parameters differ in whether they are early- or late-bound" ) 
1344+         . with_code ( E0195 ) ; 
1345+     for  mismatch in  mismatched { 
1346+         match  mismatch { 
1347+             LateEarlyMismatch :: EarlyInImpl ( 
1348+                 impl_param_def_id, 
1349+                 trait_param_def_id, 
1350+                 early_bound_region, 
1351+             )  => { 
1352+                 let  mut  multispan = MultiSpan :: from_spans ( vec ! [ 
1353+                     tcx. def_span( impl_param_def_id) , 
1354+                     tcx. def_span( trait_param_def_id) , 
1355+                 ] ) ; 
1356+                 multispan
1357+                     . push_span_label ( tcx. def_span ( tcx. parent ( impl_m. def_id ) ) ,  "in this impl..." ) ; 
1358+                 multispan
1359+                     . push_span_label ( tcx. def_span ( tcx. parent ( trait_m. def_id ) ) ,  "in this trait..." ) ; 
1360+                 multispan. push_span_label ( 
1361+                     tcx. def_span ( impl_param_def_id) , 
1362+                     format ! ( "`{}` is early-bound" ,  tcx. item_name( impl_param_def_id) ) , 
1363+                 ) ; 
1364+                 multispan. push_span_label ( 
1365+                     tcx. def_span ( trait_param_def_id) , 
1366+                     format ! ( "`{}` is late-bound" ,  tcx. item_name( trait_param_def_id) ) , 
1367+                 ) ; 
1368+                 if  let  Some ( span)  =
1369+                     find_region_in_predicates ( tcx,  impl_m. def_id ,  early_bound_region) 
1370+                 { 
1371+                     multispan. push_span_label ( 
1372+                         span, 
1373+                         format ! ( 
1374+                             "this lifetime bound makes `{}` early-bound" , 
1375+                             tcx. item_name( impl_param_def_id) 
1376+                         ) , 
1377+                     ) ; 
1378+                 } 
1379+                 diag. span_note ( 
1380+                     multispan, 
1381+                     format ! ( 
1382+                         "the late-boundedness of `{}` differs" , 
1383+                         tcx. item_name( impl_param_def_id) 
1384+                     ) , 
1385+                 ) ; 
1386+             } 
1387+             LateEarlyMismatch :: LateInImpl ( 
1388+                 impl_param_def_id, 
1389+                 trait_param_def_id, 
1390+                 early_bound_region, 
1391+             )  => { 
1392+                 let  mut  multispan = MultiSpan :: from_spans ( vec ! [ 
1393+                     tcx. def_span( impl_param_def_id) , 
1394+                     tcx. def_span( trait_param_def_id) , 
1395+                 ] ) ; 
1396+                 multispan
1397+                     . push_span_label ( tcx. def_span ( tcx. parent ( impl_m. def_id ) ) ,  "in this impl..." ) ; 
1398+                 multispan
1399+                     . push_span_label ( tcx. def_span ( tcx. parent ( trait_m. def_id ) ) ,  "in this trait..." ) ; 
1400+                 multispan. push_span_label ( 
1401+                     tcx. def_span ( impl_param_def_id) , 
1402+                     format ! ( "`{}` is late-bound" ,  tcx. item_name( impl_param_def_id) ) , 
1403+                 ) ; 
1404+                 multispan. push_span_label ( 
1405+                     tcx. def_span ( trait_param_def_id) , 
1406+                     format ! ( "`{}` is early-bound" ,  tcx. item_name( trait_param_def_id) ) , 
1407+                 ) ; 
1408+                 if  let  Some ( span)  =
1409+                     find_region_in_predicates ( tcx,  trait_m. def_id ,  early_bound_region) 
1410+                 { 
1411+                     multispan. push_span_label ( 
1412+                         span, 
1413+                         format ! ( 
1414+                             "this lifetime bound makes `{}` early-bound" , 
1415+                             tcx. item_name( trait_param_def_id) 
1416+                         ) , 
1417+                     ) ; 
1418+                 } 
1419+                 diag. span_note ( 
1420+                     multispan, 
1421+                     format ! ( 
1422+                         "the late-boundedness of `{}` differs" , 
1423+                         tcx. item_name( impl_param_def_id) 
1424+                     ) , 
1425+                 ) ; 
1426+             } 
1427+         } 
1428+     } 
1429+ 
1430+     Some ( diag. emit ( ) ) 
1431+ } 
1432+ 
1433+ fn  find_region_in_predicates < ' tcx > ( 
1434+     tcx :  TyCtxt < ' tcx > , 
1435+     def_id :  DefId , 
1436+     early_bound_region :  ty:: Region < ' tcx > , 
1437+ )  -> Option < Span >  { 
1438+     for  ( pred,  span)  in  tcx. explicit_predicates_of ( def_id) . instantiate_identity ( tcx)  { 
1439+         if  pred. visit_with ( & mut  FindRegion ( early_bound_region) ) . is_break ( )  { 
1440+             return  Some ( span) ; 
1441+         } 
1442+     } 
1443+ 
1444+     struct  FindRegion < ' tcx > ( ty:: Region < ' tcx > ) ; 
1445+     impl < ' tcx >  TypeVisitor < TyCtxt < ' tcx > >  for  FindRegion < ' tcx >  { 
1446+         type  Result  = ControlFlow < ( ) > ; 
1447+         fn  visit_region ( & mut  self ,  r :  ty:: Region < ' tcx > )  -> Self :: Result  { 
1448+             if  r == self . 0  {  ControlFlow :: Break ( ( ) )  }  else  {  ControlFlow :: Continue ( ( ) )  } 
1449+         } 
1450+     } 
1451+ 
1452+     None 
1453+ } 
1454+ 
12241455#[ instrument( level = "debug" ,  skip( infcx) ) ]  
12251456fn  extract_spans_for_error_reporting < ' tcx > ( 
12261457    infcx :  & infer:: InferCtxt < ' tcx > , 
0 commit comments