@@ -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
@@ -436,6 +430,121 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
436430 & outlives_environment,
437431 ) ;
438432
433+ Ok ( ( ) )
434+ } )
435+ }
436+
437+ pub fn collect_trait_impl_trait_tys < ' tcx > (
438+ tcx : TyCtxt < ' tcx > ,
439+ def_id : DefId ,
440+ ) -> Result < & ' tcx FxHashMap < DefId , Ty < ' tcx > > , ErrorGuaranteed > {
441+ let impl_m = tcx. opt_associated_item ( def_id) . unwrap ( ) ;
442+ let trait_m = tcx. opt_associated_item ( impl_m. trait_item_def_id . unwrap ( ) ) . unwrap ( ) ;
443+ let impl_trait_ref = tcx. impl_trait_ref ( impl_m. impl_container ( tcx) . unwrap ( ) ) . unwrap ( ) ;
444+ let param_env = tcx. param_env ( def_id) ;
445+
446+ let trait_to_impl_substs = impl_trait_ref. substs ;
447+
448+ let impl_m_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( impl_m. def_id . expect_local ( ) ) ;
449+ let return_span = tcx. hir ( ) . fn_decl_by_hir_id ( impl_m_hir_id) . unwrap ( ) . output . span ( ) ;
450+ let cause = ObligationCause :: new (
451+ return_span,
452+ impl_m_hir_id,
453+ ObligationCauseCode :: CompareImplItemObligation {
454+ impl_item_def_id : impl_m. def_id . expect_local ( ) ,
455+ trait_item_def_id : trait_m. def_id ,
456+ kind : impl_m. kind ,
457+ } ,
458+ ) ;
459+
460+ // Create mapping from impl to placeholder.
461+ let impl_to_placeholder_substs = InternalSubsts :: identity_for_item ( tcx, impl_m. def_id ) ;
462+
463+ // Create mapping from trait to placeholder.
464+ let trait_to_placeholder_substs =
465+ impl_to_placeholder_substs. rebase_onto ( tcx, impl_m. container_id ( tcx) , trait_to_impl_substs) ;
466+
467+ tcx. infer_ctxt ( ) . enter ( |ref infcx| {
468+ let ocx = ObligationCtxt :: new ( infcx) ;
469+
470+ let norm_cause = ObligationCause :: misc ( return_span, impl_m_hir_id) ;
471+ let impl_return_ty = ocx. normalize (
472+ norm_cause. clone ( ) ,
473+ param_env,
474+ infcx
475+ . replace_bound_vars_with_fresh_vars (
476+ return_span,
477+ infer:: HigherRankedType ,
478+ tcx. fn_sig ( impl_m. def_id ) ,
479+ )
480+ . output ( ) ,
481+ ) ;
482+
483+ let mut collector =
484+ ImplTraitInTraitCollector :: new ( & ocx, return_span, param_env, impl_m_hir_id) ;
485+ let unnormalized_trait_return_ty = tcx
486+ . liberate_late_bound_regions (
487+ impl_m. def_id ,
488+ tcx. bound_fn_sig ( trait_m. def_id ) . subst ( tcx, trait_to_placeholder_substs) ,
489+ )
490+ . output ( )
491+ . fold_with ( & mut collector) ;
492+ let trait_return_ty =
493+ ocx. normalize ( norm_cause. clone ( ) , param_env, unnormalized_trait_return_ty) ;
494+
495+ let wf_tys = FxHashSet :: from_iter ( [ unnormalized_trait_return_ty, trait_return_ty] ) ;
496+
497+ match infcx. at ( & cause, param_env) . eq ( trait_return_ty, impl_return_ty) {
498+ Ok ( infer:: InferOk { value : ( ) , obligations } ) => {
499+ ocx. register_obligations ( obligations) ;
500+ }
501+ Err ( terr) => {
502+ let mut diag = struct_span_err ! (
503+ tcx. sess,
504+ cause. span( ) ,
505+ E0053 ,
506+ "method `{}` has an incompatible return type for trait" ,
507+ trait_m. name
508+ ) ;
509+ let hir = tcx. hir ( ) ;
510+ infcx. note_type_err (
511+ & mut diag,
512+ & cause,
513+ hir. get_if_local ( impl_m. def_id )
514+ . and_then ( |node| node. fn_decl ( ) )
515+ . map ( |decl| ( decl. output . span ( ) , "return type in trait" . to_owned ( ) ) ) ,
516+ Some ( infer:: ValuePairs :: Terms ( ExpectedFound {
517+ expected : trait_return_ty. into ( ) ,
518+ found : impl_return_ty. into ( ) ,
519+ } ) ) ,
520+ terr,
521+ false ,
522+ false ,
523+ ) ;
524+ return Err ( diag. emit ( ) ) ;
525+ }
526+ }
527+
528+ // Check that all obligations are satisfied by the implementation's
529+ // RPITs.
530+ let errors = ocx. select_all_or_error ( ) ;
531+ if !errors. is_empty ( ) {
532+ let reported = infcx. report_fulfillment_errors ( & errors, None , false ) ;
533+ return Err ( reported) ;
534+ }
535+
536+ // Finally, resolve all regions. This catches wily misuses of
537+ // lifetime parameters.
538+ let outlives_environment = OutlivesEnvironment :: with_bounds (
539+ param_env,
540+ Some ( infcx) ,
541+ infcx. implied_bounds_tys ( param_env, impl_m_hir_id, wf_tys) ,
542+ ) ;
543+ infcx. check_region_obligations_and_report_errors (
544+ impl_m. def_id . expect_local ( ) ,
545+ & outlives_environment,
546+ ) ;
547+
439548 let mut collected_tys = FxHashMap :: default ( ) ;
440549 for ( def_id, ( ty, substs) ) in collector. types {
441550 match infcx. fully_resolve ( ty) {
@@ -1322,7 +1431,7 @@ pub(crate) fn compare_ty_impl<'tcx>(
13221431 } ) ( ) ;
13231432}
13241433
1325- /// The equivalent of [compare_predicates_and_trait_impl_trait_tys ], but for associated types
1434+ /// The equivalent of [compare_predicate_entailment ], but for associated types
13261435/// instead of associated functions.
13271436fn compare_type_predicate_entailment < ' tcx > (
13281437 tcx : TyCtxt < ' tcx > ,
0 commit comments