@@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
15
15
use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
16
16
use rustc_middle:: ty:: util:: ExplicitSelf ;
17
17
use rustc_middle:: ty:: {
18
- self , DefIdTree , Ty , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitable ,
18
+ self , AssocItem , DefIdTree , Ty , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitable ,
19
19
} ;
20
20
use rustc_middle:: ty:: { GenericParamDefKind , ToPredicate , TyCtxt } ;
21
21
use rustc_span:: Span ;
@@ -68,7 +68,10 @@ pub(crate) fn compare_impl_method<'tcx>(
68
68
return ;
69
69
}
70
70
71
- tcx. ensure ( ) . compare_predicates_and_trait_impl_trait_tys ( impl_m. def_id ) ;
71
+ if let Err ( _) = compare_predicate_entailment ( tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
72
+ {
73
+ return ;
74
+ }
72
75
}
73
76
74
77
/// This function is best explained by example. Consider a trait:
@@ -137,15 +140,13 @@ pub(crate) fn compare_impl_method<'tcx>(
137
140
///
138
141
/// Finally we register each of these predicates as an obligation and check that
139
142
/// they hold.
140
- pub ( super ) fn compare_predicates_and_trait_impl_trait_tys < ' tcx > (
143
+ fn compare_predicate_entailment < ' tcx > (
141
144
tcx : TyCtxt < ' tcx > ,
142
- def_id : DefId ,
143
- ) -> Result < & ' tcx FxHashMap < DefId , Ty < ' tcx > > , ErrorGuaranteed > {
144
- let impl_m = tcx. opt_associated_item ( def_id) . unwrap ( ) ;
145
- let impl_m_span = tcx. def_span ( def_id) ;
146
- let trait_m = tcx. opt_associated_item ( impl_m. trait_item_def_id . unwrap ( ) ) . unwrap ( ) ;
147
- let impl_trait_ref = tcx. impl_trait_ref ( impl_m. impl_container ( tcx) . unwrap ( ) ) . unwrap ( ) ;
148
-
145
+ impl_m : & AssocItem ,
146
+ impl_m_span : Span ,
147
+ trait_m : & AssocItem ,
148
+ impl_trait_ref : ty:: TraitRef < ' tcx > ,
149
+ ) -> Result < ( ) , ErrorGuaranteed > {
149
150
let trait_to_impl_substs = impl_trait_ref. substs ;
150
151
151
152
// This node-id should be used for the `body_id` field on each
@@ -164,7 +165,6 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
164
165
kind : impl_m. kind ,
165
166
} ,
166
167
) ;
167
- let return_span = tcx. hir ( ) . fn_decl_by_hir_id ( impl_m_hir_id) . unwrap ( ) . output . span ( ) ;
168
168
169
169
// Create mapping from impl to placeholder.
170
170
let impl_to_placeholder_substs = InternalSubsts :: identity_for_item ( tcx, impl_m. def_id ) ;
@@ -270,12 +270,6 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
270
270
271
271
let trait_sig = tcx. bound_fn_sig ( trait_m. def_id ) . subst ( tcx, trait_to_placeholder_substs) ;
272
272
let trait_sig = tcx. liberate_late_bound_regions ( impl_m. def_id , trait_sig) ;
273
- let mut collector =
274
- ImplTraitInTraitCollector :: new ( & ocx, return_span, param_env, impl_m_hir_id) ;
275
- // FIXME(RPITIT): This should only be needed on the output type, but
276
- // RPITIT placeholders shouldn't show up anywhere except for there,
277
- // so I think this is fine.
278
- let trait_sig = trait_sig. fold_with ( & mut collector) ;
279
273
280
274
// Next, add all inputs and output as well-formed tys. Importantly,
281
275
// we have to do this before normalization, since the normalized ty may
@@ -422,6 +416,121 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
422
416
& outlives_environment,
423
417
) ;
424
418
419
+ Ok ( ( ) )
420
+ } )
421
+ }
422
+
423
+ pub fn collect_trait_impl_trait_tys < ' tcx > (
424
+ tcx : TyCtxt < ' tcx > ,
425
+ def_id : DefId ,
426
+ ) -> Result < & ' tcx FxHashMap < DefId , Ty < ' tcx > > , ErrorGuaranteed > {
427
+ let impl_m = tcx. opt_associated_item ( def_id) . unwrap ( ) ;
428
+ let trait_m = tcx. opt_associated_item ( impl_m. trait_item_def_id . unwrap ( ) ) . unwrap ( ) ;
429
+ let impl_trait_ref = tcx. impl_trait_ref ( impl_m. impl_container ( tcx) . unwrap ( ) ) . unwrap ( ) ;
430
+ let param_env = tcx. param_env ( def_id) ;
431
+
432
+ let trait_to_impl_substs = impl_trait_ref. substs ;
433
+
434
+ let impl_m_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( impl_m. def_id . expect_local ( ) ) ;
435
+ let return_span = tcx. hir ( ) . fn_decl_by_hir_id ( impl_m_hir_id) . unwrap ( ) . output . span ( ) ;
436
+ let cause = ObligationCause :: new (
437
+ return_span,
438
+ impl_m_hir_id,
439
+ ObligationCauseCode :: CompareImplItemObligation {
440
+ impl_item_def_id : impl_m. def_id . expect_local ( ) ,
441
+ trait_item_def_id : trait_m. def_id ,
442
+ kind : impl_m. kind ,
443
+ } ,
444
+ ) ;
445
+
446
+ // Create mapping from impl to placeholder.
447
+ let impl_to_placeholder_substs = InternalSubsts :: identity_for_item ( tcx, impl_m. def_id ) ;
448
+
449
+ // Create mapping from trait to placeholder.
450
+ let trait_to_placeholder_substs =
451
+ impl_to_placeholder_substs. rebase_onto ( tcx, impl_m. container_id ( tcx) , trait_to_impl_substs) ;
452
+
453
+ tcx. infer_ctxt ( ) . enter ( |ref infcx| {
454
+ let ocx = ObligationCtxt :: new ( infcx) ;
455
+
456
+ let norm_cause = ObligationCause :: misc ( return_span, impl_m_hir_id) ;
457
+ let impl_return_ty = ocx. normalize (
458
+ norm_cause. clone ( ) ,
459
+ param_env,
460
+ infcx
461
+ . replace_bound_vars_with_fresh_vars (
462
+ return_span,
463
+ infer:: HigherRankedType ,
464
+ tcx. fn_sig ( impl_m. def_id ) ,
465
+ )
466
+ . output ( ) ,
467
+ ) ;
468
+
469
+ let mut collector =
470
+ ImplTraitInTraitCollector :: new ( & ocx, return_span, param_env, impl_m_hir_id) ;
471
+ let unnormalized_trait_return_ty = tcx
472
+ . liberate_late_bound_regions (
473
+ impl_m. def_id ,
474
+ tcx. bound_fn_sig ( trait_m. def_id ) . subst ( tcx, trait_to_placeholder_substs) ,
475
+ )
476
+ . output ( )
477
+ . fold_with ( & mut collector) ;
478
+ let trait_return_ty =
479
+ ocx. normalize ( norm_cause. clone ( ) , param_env, unnormalized_trait_return_ty) ;
480
+
481
+ let wf_tys = FxHashSet :: from_iter ( [ unnormalized_trait_return_ty, trait_return_ty] ) ;
482
+
483
+ match infcx. at ( & cause, param_env) . eq ( trait_return_ty, impl_return_ty) {
484
+ Ok ( infer:: InferOk { value : ( ) , obligations } ) => {
485
+ ocx. register_obligations ( obligations) ;
486
+ }
487
+ Err ( terr) => {
488
+ let mut diag = struct_span_err ! (
489
+ tcx. sess,
490
+ cause. span( ) ,
491
+ E0053 ,
492
+ "method `{}` has an incompatible return type for trait" ,
493
+ trait_m. name
494
+ ) ;
495
+ let hir = tcx. hir ( ) ;
496
+ infcx. note_type_err (
497
+ & mut diag,
498
+ & cause,
499
+ hir. get_if_local ( impl_m. def_id )
500
+ . and_then ( |node| node. fn_decl ( ) )
501
+ . map ( |decl| ( decl. output . span ( ) , "return type in trait" . to_owned ( ) ) ) ,
502
+ Some ( infer:: ValuePairs :: Terms ( ExpectedFound {
503
+ expected : trait_return_ty. into ( ) ,
504
+ found : impl_return_ty. into ( ) ,
505
+ } ) ) ,
506
+ terr,
507
+ false ,
508
+ false ,
509
+ ) ;
510
+ return Err ( diag. emit ( ) ) ;
511
+ }
512
+ }
513
+
514
+ // Check that all obligations are satisfied by the implementation's
515
+ // RPITs.
516
+ let errors = ocx. select_all_or_error ( ) ;
517
+ if !errors. is_empty ( ) {
518
+ let reported = infcx. report_fulfillment_errors ( & errors, None , false ) ;
519
+ return Err ( reported) ;
520
+ }
521
+
522
+ // Finally, resolve all regions. This catches wily misuses of
523
+ // lifetime parameters.
524
+ let outlives_environment = OutlivesEnvironment :: with_bounds (
525
+ param_env,
526
+ Some ( infcx) ,
527
+ infcx. implied_bounds_tys ( param_env, impl_m_hir_id, wf_tys) ,
528
+ ) ;
529
+ infcx. check_region_obligations_and_report_errors (
530
+ impl_m. def_id . expect_local ( ) ,
531
+ & outlives_environment,
532
+ ) ;
533
+
425
534
let mut collected_tys = FxHashMap :: default ( ) ;
426
535
for ( def_id, ( ty, substs) ) in collector. types {
427
536
match infcx. fully_resolve ( ty) {
@@ -1307,7 +1416,7 @@ pub(crate) fn compare_ty_impl<'tcx>(
1307
1416
} ) ( ) ;
1308
1417
}
1309
1418
1310
- /// The equivalent of [compare_predicates_and_trait_impl_trait_tys ], but for associated types
1419
+ /// The equivalent of [compare_predicate_entailment ], but for associated types
1311
1420
/// instead of associated functions.
1312
1421
fn compare_type_predicate_entailment < ' tcx > (
1313
1422
tcx : TyCtxt < ' tcx > ,
0 commit comments