@@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
1515use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
1616use rustc_middle:: ty:: util:: ExplicitSelf ;
1717use rustc_middle:: ty:: {
18- self , DefIdTree , Ty , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitable ,
18+ self , AssocItem , DefIdTree , Ty , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitable ,
1919} ;
2020use rustc_middle:: ty:: { GenericParamDefKind , ToPredicate , TyCtxt } ;
2121use rustc_span:: Span ;
@@ -68,7 +68,10 @@ pub(crate) fn compare_impl_method<'tcx>(
6868 return ;
6969 }
7070
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+ }
7275}
7376
7477/// This function is best explained by example. Consider a trait:
@@ -137,15 +140,13 @@ pub(crate) fn compare_impl_method<'tcx>(
137140///
138141/// Finally we register each of these predicates as an obligation and check that
139142/// they hold.
140- pub ( super ) fn compare_predicates_and_trait_impl_trait_tys < ' tcx > (
143+ fn compare_predicate_entailment < ' tcx > (
141144 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 > {
149150 let trait_to_impl_substs = impl_trait_ref. substs ;
150151
151152 // 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>(
164165 kind : impl_m. kind ,
165166 } ,
166167 ) ;
167- let return_span = tcx. hir ( ) . fn_decl_by_hir_id ( impl_m_hir_id) . unwrap ( ) . output . span ( ) ;
168168
169169 // Create mapping from impl to placeholder.
170170 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>(
270270
271271 let trait_sig = tcx. bound_fn_sig ( trait_m. def_id ) . subst ( tcx, trait_to_placeholder_substs) ;
272272 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) ;
279273
280274 // Next, add all inputs and output as well-formed tys. Importantly,
281275 // 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>(
422416 & outlives_environment,
423417 ) ;
424418
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+
425534 let mut collected_tys = FxHashMap :: default ( ) ;
426535 for ( def_id, ( ty, substs) ) in collector. types {
427536 match infcx. fully_resolve ( ty) {
@@ -1307,7 +1416,7 @@ pub(crate) fn compare_ty_impl<'tcx>(
13071416 } ) ( ) ;
13081417}
13091418
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
13111420/// instead of associated functions.
13121421fn compare_type_predicate_entailment < ' tcx > (
13131422 tcx : TyCtxt < ' tcx > ,
0 commit comments