@@ -14,6 +14,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
1414use rustc_infer:: infer:: { self , InferCtxt , TyCtxtInferExt } ;
1515use rustc_infer:: traits:: util;
1616use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
17+ use rustc_middle:: ty:: fold:: BottomUpFolder ;
1718use rustc_middle:: ty:: util:: ExplicitSelf ;
1819use rustc_middle:: ty:: {
1920 self , GenericArgs , Ty , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitableExt ,
@@ -661,8 +662,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
661662 let trait_m = tcx. opt_associated_item ( impl_m. trait_item_def_id . unwrap ( ) ) . unwrap ( ) ;
662663 let impl_trait_ref =
663664 tcx. impl_trait_ref ( impl_m. impl_container ( tcx) . unwrap ( ) ) . unwrap ( ) . instantiate_identity ( ) ;
664- let param_env = tcx. param_env ( impl_m_def_id) ;
665-
666665 // First, check a few of the same things as `compare_impl_method`,
667666 // just so we don't ICE during substitution later.
668667 check_method_is_structurally_compatible ( tcx, impl_m, trait_m, impl_trait_ref, true ) ?;
@@ -688,13 +687,26 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
688687 let trait_to_placeholder_args =
689688 impl_to_placeholder_args. rebase_onto ( tcx, impl_m. container_id ( tcx) , trait_to_impl_args) ;
690689
690+ let hybrid_preds = tcx
691+ . predicates_of ( impl_m. container_id ( tcx) )
692+ . instantiate_identity ( tcx)
693+ . into_iter ( )
694+ . chain ( tcx. predicates_of ( trait_m. def_id ) . instantiate_own ( tcx, trait_to_placeholder_args) )
695+ . map ( |( clause, _) | clause) ;
696+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses_from_iter ( hybrid_preds) , Reveal :: UserFacing ) ;
697+ let param_env = traits:: normalize_param_env_or_error (
698+ tcx,
699+ param_env,
700+ ObligationCause :: misc ( tcx. def_span ( impl_m_def_id) , impl_m_def_id) ,
701+ ) ;
702+
691703 let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
692704 let ocx = ObligationCtxt :: new ( infcx) ;
693705
694706 // Normalize the impl signature with fresh variables for lifetime inference.
695- let norm_cause = ObligationCause :: misc ( return_span, impl_m_def_id) ;
707+ let misc_cause = ObligationCause :: misc ( return_span, impl_m_def_id) ;
696708 let impl_sig = ocx. normalize (
697- & norm_cause ,
709+ & misc_cause ,
698710 param_env,
699711 tcx. liberate_late_bound_regions (
700712 impl_m. def_id ,
@@ -725,12 +737,68 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
725737 ) ;
726738 }
727739
728- let trait_sig = ocx. normalize ( & norm_cause , param_env, unnormalized_trait_sig) ;
740+ let trait_sig = ocx. normalize ( & misc_cause , param_env, unnormalized_trait_sig) ;
729741 trait_sig. error_reported ( ) ?;
730742 let trait_return_ty = trait_sig. output ( ) ;
731743
744+ // RPITITs are allowed to use the implied predicates of the method that
745+ // defines them. This is because we want code like:
746+ // ```
747+ // trait Foo {
748+ // fn test<'a, T>(_: &'a T) -> impl Sized;
749+ // }
750+ // impl Foo for () {
751+ // fn test<'a, T>(x: &'a T) -> &'a T { x }
752+ // }
753+ // ```
754+ // .. to compile. However, since we use both the normalized and unnormalized
755+ // inputs and outputs from the substituted trait signature, we will end up
756+ // seeing the hidden type of an RPIT in the signature itself. Naively, this
757+ // means that we will use the hidden type to imply the hidden type's own
758+ // well-formedness.
759+ //
760+ // To avoid this, we replace the infer vars used for hidden type inference
761+ // with placeholders, which imply nothing about outlives bounds, and then
762+ // prove below that the hidden types are well formed.
763+ let universe = infcx. create_next_universe ( ) ;
764+ let mut idx = 0 ;
765+ let mapping: FxHashMap < _ , _ > = collector
766+ . types
767+ . iter ( )
768+ . map ( |( _, & ( ty, _) ) | {
769+ assert ! (
770+ infcx. resolve_vars_if_possible( ty) == ty && ty. is_ty_var( ) ,
771+ "{ty:?} should not have been constrained via normalization" ,
772+ ty = infcx. resolve_vars_if_possible( ty)
773+ ) ;
774+ idx += 1 ;
775+ (
776+ ty,
777+ Ty :: new_placeholder (
778+ tcx,
779+ ty:: Placeholder {
780+ universe,
781+ bound : ty:: BoundTy {
782+ var : ty:: BoundVar :: from_usize ( idx) ,
783+ kind : ty:: BoundTyKind :: Anon ,
784+ } ,
785+ } ,
786+ ) ,
787+ )
788+ } )
789+ . collect ( ) ;
790+ let mut type_mapper = BottomUpFolder {
791+ tcx,
792+ ty_op : |ty| * mapping. get ( & ty) . unwrap_or ( & ty) ,
793+ lt_op : |lt| lt,
794+ ct_op : |ct| ct,
795+ } ;
732796 let wf_tys = FxIndexSet :: from_iter (
733- unnormalized_trait_sig. inputs_and_output . iter ( ) . chain ( trait_sig. inputs_and_output . iter ( ) ) ,
797+ unnormalized_trait_sig
798+ . inputs_and_output
799+ . iter ( )
800+ . chain ( trait_sig. inputs_and_output . iter ( ) )
801+ . map ( |ty| ty. fold_with ( & mut type_mapper) ) ,
734802 ) ;
735803
736804 match ocx. eq ( & cause, param_env, trait_return_ty, impl_return_ty) {
@@ -787,6 +855,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
787855 }
788856 }
789857
858+ // FIXME: This has the same issue as #108544, but since this isn't breaking
859+ // existing code, I'm not particularly inclined to do the same hack as above
860+ // where we process wf obligations manually. This can be fixed in a forward-
861+ // compatible way later.
862+ let collected_types = collector. types ;
863+ for ( _, & ( ty, _) ) in & collected_types {
864+ ocx. register_obligation ( traits:: Obligation :: new (
865+ tcx,
866+ misc_cause. clone ( ) ,
867+ param_env,
868+ ty:: ClauseKind :: WellFormed ( ty. into ( ) ) ,
869+ ) ) ;
870+ }
871+
790872 // Check that all obligations are satisfied by the implementation's
791873 // RPITs.
792874 let errors = ocx. select_all_or_error ( ) ;
@@ -795,8 +877,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
795877 return Err ( reported) ;
796878 }
797879
798- let collected_types = collector. types ;
799-
800880 // Finally, resolve all regions. This catches wily misuses of
801881 // lifetime parameters.
802882 let outlives_env = OutlivesEnvironment :: with_bounds (
0 commit comments