@@ -5,7 +5,7 @@ use std::iter;
5
5
use hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
6
6
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
7
7
use 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} ;
9
9
use rustc_hir:: def:: { DefKind , Res } ;
10
10
use rustc_hir:: intravisit:: VisitorExt ;
11
11
use rustc_hir:: { self as hir, AmbigArg , GenericParamKind , ImplItemKind , intravisit} ;
@@ -14,10 +14,10 @@ use rustc_infer::traits::util;
14
14
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
15
15
use rustc_middle:: ty:: {
16
16
self , BottomUpFolder , GenericArgs , GenericParamDefKind , Ty , TyCtxt , TypeFoldable , TypeFolder ,
17
- TypeSuperFoldable , TypeVisitableExt , TypingMode , Upcast ,
17
+ TypeSuperFoldable , TypeVisitable , TypeVisitableExt , TypeVisitor , TypingMode , Upcast ,
18
18
} ;
19
19
use rustc_middle:: { bug, span_bug} ;
20
- use rustc_span:: Span ;
20
+ use rustc_span:: { DUMMY_SP , Span } ;
21
21
use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ;
22
22
use rustc_trait_selection:: infer:: InferCtxtExt ;
23
23
use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
@@ -1141,6 +1141,10 @@ fn check_region_bounds_on_impl_item<'tcx>(
1141
1141
return Ok ( ( ) ) ;
1142
1142
}
1143
1143
1144
+ if !delay && let Some ( guar) = check_region_late_boundedness ( tcx, impl_m, trait_m) {
1145
+ return Err ( guar) ;
1146
+ }
1147
+
1144
1148
let span = tcx
1145
1149
. hir_get_generics ( impl_m. def_id . expect_local ( ) )
1146
1150
. expect ( "expected impl item to have generics or else we can't compare them" )
@@ -1221,6 +1225,231 @@ fn check_region_bounds_on_impl_item<'tcx>(
1221
1225
Err ( reported)
1222
1226
}
1223
1227
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
+ let Ok ( ( ) ) = ocx. eq (
1257
+ & ObligationCause :: dummy ( ) ,
1258
+ param_env,
1259
+ ty:: Binder :: dummy ( trait_m_sig) ,
1260
+ ty:: Binder :: dummy ( impl_m_sig) ,
1261
+ ) else {
1262
+ return None ;
1263
+ } ;
1264
+
1265
+ let errors = ocx. select_where_possible ( ) ;
1266
+ if !errors. is_empty ( ) {
1267
+ return None ;
1268
+ }
1269
+
1270
+ let mut mismatched = vec ! [ ] ;
1271
+
1272
+ let impl_generics = tcx. generics_of ( impl_m. def_id ) ;
1273
+ for ( id_arg, arg) in
1274
+ std:: iter:: zip ( ty:: GenericArgs :: identity_for_item ( tcx, impl_m. def_id ) , impl_m_args)
1275
+ {
1276
+ if let ty:: GenericArgKind :: Lifetime ( r) = arg. unpack ( )
1277
+ && let ty:: ReVar ( vid) = r. kind ( )
1278
+ && let r = infcx
1279
+ . inner
1280
+ . borrow_mut ( )
1281
+ . unwrap_region_constraints ( )
1282
+ . opportunistic_resolve_var ( tcx, vid)
1283
+ && let ty:: ReLateParam ( ty:: LateParamRegion {
1284
+ kind : ty:: LateParamRegionKind :: Named ( trait_param_def_id, _) ,
1285
+ ..
1286
+ } ) = r. kind ( )
1287
+ && let ty:: ReEarlyParam ( ebr) = id_arg. expect_region ( ) . kind ( )
1288
+ {
1289
+ mismatched. push ( LateEarlyMismatch :: EarlyInImpl (
1290
+ impl_generics. region_param ( ebr, tcx) . def_id ,
1291
+ trait_param_def_id,
1292
+ id_arg. expect_region ( ) ,
1293
+ ) ) ;
1294
+ }
1295
+ }
1296
+
1297
+ let trait_generics = tcx. generics_of ( trait_m. def_id ) ;
1298
+ for ( id_arg, arg) in
1299
+ std:: iter:: zip ( ty:: GenericArgs :: identity_for_item ( tcx, trait_m. def_id ) , trait_m_args)
1300
+ {
1301
+ if let ty:: GenericArgKind :: Lifetime ( r) = arg. unpack ( )
1302
+ && let ty:: ReVar ( vid) = r. kind ( )
1303
+ && let r = infcx
1304
+ . inner
1305
+ . borrow_mut ( )
1306
+ . unwrap_region_constraints ( )
1307
+ . opportunistic_resolve_var ( tcx, vid)
1308
+ && let ty:: ReLateParam ( ty:: LateParamRegion {
1309
+ kind : ty:: LateParamRegionKind :: Named ( impl_param_def_id, _) ,
1310
+ ..
1311
+ } ) = r. kind ( )
1312
+ && let ty:: ReEarlyParam ( ebr) = id_arg. expect_region ( ) . kind ( )
1313
+ {
1314
+ mismatched. push ( LateEarlyMismatch :: LateInImpl (
1315
+ impl_param_def_id,
1316
+ trait_generics. region_param ( ebr, tcx) . def_id ,
1317
+ id_arg. expect_region ( ) ,
1318
+ ) ) ;
1319
+ }
1320
+ }
1321
+
1322
+ if mismatched. is_empty ( ) {
1323
+ return None ;
1324
+ }
1325
+
1326
+ let spans: Vec < _ > = mismatched
1327
+ . iter ( )
1328
+ . map ( |param| {
1329
+ let ( LateEarlyMismatch :: EarlyInImpl ( impl_param_def_id, ..)
1330
+ | LateEarlyMismatch :: LateInImpl ( impl_param_def_id, ..) ) = param;
1331
+ tcx. def_span ( impl_param_def_id)
1332
+ } )
1333
+ . collect ( ) ;
1334
+
1335
+ let mut diag = tcx
1336
+ . dcx ( )
1337
+ . struct_span_err (
1338
+ spans,
1339
+ "lifetime parameters do not match the trait definition, \
1340
+ since they differ in late-boundedness",
1341
+ )
1342
+ . with_code ( E0195 ) ;
1343
+ for mismatch in mismatched {
1344
+ match mismatch {
1345
+ LateEarlyMismatch :: EarlyInImpl (
1346
+ impl_param_def_id,
1347
+ trait_param_def_id,
1348
+ early_bound_region,
1349
+ ) => {
1350
+ let mut multispan = MultiSpan :: from_spans ( vec ! [
1351
+ tcx. def_span( impl_param_def_id) ,
1352
+ tcx. def_span( trait_param_def_id) ,
1353
+ ] ) ;
1354
+ multispan
1355
+ . push_span_label ( tcx. def_span ( tcx. parent ( impl_m. def_id ) ) , "in this impl..." ) ;
1356
+ multispan
1357
+ . push_span_label ( tcx. def_span ( tcx. parent ( trait_m. def_id ) ) , "in this trait..." ) ;
1358
+ multispan. push_span_label (
1359
+ tcx. def_span ( impl_param_def_id) ,
1360
+ format ! ( "`{}` is early-bound" , tcx. item_name( impl_param_def_id) ) ,
1361
+ ) ;
1362
+ multispan. push_span_label (
1363
+ tcx. def_span ( trait_param_def_id) ,
1364
+ format ! ( "`{}` is late-bound" , tcx. item_name( trait_param_def_id) ) ,
1365
+ ) ;
1366
+ if let Some ( span) =
1367
+ find_region_in_predicates ( tcx, impl_m. def_id , early_bound_region)
1368
+ {
1369
+ multispan. push_span_label (
1370
+ span,
1371
+ format ! (
1372
+ "this lifetime bound makes `{}` early-bound" ,
1373
+ tcx. item_name( impl_param_def_id)
1374
+ ) ,
1375
+ ) ;
1376
+ }
1377
+ diag. span_note (
1378
+ multispan,
1379
+ format ! (
1380
+ "the late-boundedness of `{}` differs" ,
1381
+ tcx. item_name( impl_param_def_id)
1382
+ ) ,
1383
+ ) ;
1384
+ }
1385
+ LateEarlyMismatch :: LateInImpl (
1386
+ impl_param_def_id,
1387
+ trait_param_def_id,
1388
+ early_bound_region,
1389
+ ) => {
1390
+ let mut multispan = MultiSpan :: from_spans ( vec ! [
1391
+ tcx. def_span( impl_param_def_id) ,
1392
+ tcx. def_span( trait_param_def_id) ,
1393
+ ] ) ;
1394
+ multispan
1395
+ . push_span_label ( tcx. def_span ( tcx. parent ( impl_m. def_id ) ) , "in this impl..." ) ;
1396
+ multispan
1397
+ . push_span_label ( tcx. def_span ( tcx. parent ( trait_m. def_id ) ) , "in this trait..." ) ;
1398
+ multispan. push_span_label (
1399
+ tcx. def_span ( impl_param_def_id) ,
1400
+ format ! ( "`{}` is late-bound" , tcx. item_name( impl_param_def_id) ) ,
1401
+ ) ;
1402
+ multispan. push_span_label (
1403
+ tcx. def_span ( trait_param_def_id) ,
1404
+ format ! ( "`{}` is early-bound" , tcx. item_name( trait_param_def_id) ) ,
1405
+ ) ;
1406
+ if let Some ( span) =
1407
+ find_region_in_predicates ( tcx, trait_m. def_id , early_bound_region)
1408
+ {
1409
+ multispan. push_span_label (
1410
+ span,
1411
+ format ! (
1412
+ "this lifetime bound makes `{}` early-bound" ,
1413
+ tcx. item_name( trait_param_def_id)
1414
+ ) ,
1415
+ ) ;
1416
+ }
1417
+ diag. span_note (
1418
+ multispan,
1419
+ format ! (
1420
+ "the late-boundedness of `{}` differs" ,
1421
+ tcx. item_name( impl_param_def_id)
1422
+ ) ,
1423
+ ) ;
1424
+ }
1425
+ }
1426
+ }
1427
+
1428
+ Some ( diag. emit ( ) )
1429
+ }
1430
+
1431
+ fn find_region_in_predicates < ' tcx > (
1432
+ tcx : TyCtxt < ' tcx > ,
1433
+ def_id : DefId ,
1434
+ early_bound_region : ty:: Region < ' tcx > ,
1435
+ ) -> Option < Span > {
1436
+ for ( pred, span) in tcx. explicit_predicates_of ( def_id) . instantiate_identity ( tcx) {
1437
+ if pred. visit_with ( & mut FindRegion ( early_bound_region) ) . is_break ( ) {
1438
+ return Some ( span) ;
1439
+ }
1440
+ }
1441
+
1442
+ struct FindRegion < ' tcx > ( ty:: Region < ' tcx > ) ;
1443
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for FindRegion < ' tcx > {
1444
+ type Result = ControlFlow < ( ) > ;
1445
+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> Self :: Result {
1446
+ if r == self . 0 { ControlFlow :: Break ( ( ) ) } else { ControlFlow :: Continue ( ( ) ) }
1447
+ }
1448
+ }
1449
+
1450
+ None
1451
+ }
1452
+
1224
1453
#[ instrument( level = "debug" , skip( infcx) ) ]
1225
1454
fn extract_spans_for_error_reporting < ' tcx > (
1226
1455
infcx : & infer:: InferCtxt < ' tcx > ,
0 commit comments