@@ -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 ,
@@ -692,9 +693,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
692693 let ocx = ObligationCtxt :: new ( infcx) ;
693694
694695 // Normalize the impl signature with fresh variables for lifetime inference.
695- let norm_cause = ObligationCause :: misc ( return_span, impl_m_def_id) ;
696+ let misc_cause = ObligationCause :: misc ( return_span, impl_m_def_id) ;
696697 let impl_sig = ocx. normalize (
697- & norm_cause ,
698+ & misc_cause ,
698699 param_env,
699700 tcx. liberate_late_bound_regions (
700701 impl_m. def_id ,
@@ -725,12 +726,68 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
725726 ) ;
726727 }
727728
728- let trait_sig = ocx. normalize ( & norm_cause , param_env, unnormalized_trait_sig) ;
729+ let trait_sig = ocx. normalize ( & misc_cause , param_env, unnormalized_trait_sig) ;
729730 trait_sig. error_reported ( ) ?;
730731 let trait_return_ty = trait_sig. output ( ) ;
731732
733+ // RPITITs are allowed to use the implied predicates of the method that
734+ // defines them. This is because we want code like:
735+ // ```
736+ // trait Foo {
737+ // fn test<'a, T>(_: &'a T) -> impl Sized;
738+ // }
739+ // impl Foo for () {
740+ // fn test<'a, T>(x: &'a T) -> &'a T { x }
741+ // }
742+ // ```
743+ // .. to compile. However, since we use both the normalized and unnormalized
744+ // inputs and outputs from the substituted trait signature, we will end up
745+ // seeing the hidden type of an RPIT in the signature itself. Naively, this
746+ // means that we will use the hidden type to imply the hidden type's own
747+ // well-formedness.
748+ //
749+ // To avoid this, we replace the infer vars used for hidden type inference
750+ // with placeholders, which imply nothing about outlives bounds, and then
751+ // prove below that the hidden types are well formed.
752+ let universe = infcx. create_next_universe ( ) ;
753+ let mut idx = 0 ;
754+ let mapping: FxHashMap < _ , _ > = collector
755+ . types
756+ . iter ( )
757+ . map ( |( _, & ( ty, _) ) | {
758+ assert ! (
759+ infcx. resolve_vars_if_possible( ty) == ty && ty. is_ty_var( ) ,
760+ "{ty:?} should not have been constrained via normalization" ,
761+ ty = infcx. resolve_vars_if_possible( ty)
762+ ) ;
763+ idx += 1 ;
764+ (
765+ ty,
766+ Ty :: new_placeholder (
767+ tcx,
768+ ty:: Placeholder {
769+ universe,
770+ bound : ty:: BoundTy {
771+ var : ty:: BoundVar :: from_usize ( idx) ,
772+ kind : ty:: BoundTyKind :: Anon ,
773+ } ,
774+ } ,
775+ ) ,
776+ )
777+ } )
778+ . collect ( ) ;
779+ let mut type_mapper = BottomUpFolder {
780+ tcx,
781+ ty_op : |ty| * mapping. get ( & ty) . unwrap_or ( & ty) ,
782+ lt_op : |lt| lt,
783+ ct_op : |ct| ct,
784+ } ;
732785 let wf_tys = FxIndexSet :: from_iter (
733- unnormalized_trait_sig. inputs_and_output . iter ( ) . chain ( trait_sig. inputs_and_output . iter ( ) ) ,
786+ unnormalized_trait_sig
787+ . inputs_and_output
788+ . iter ( )
789+ . chain ( trait_sig. inputs_and_output . iter ( ) )
790+ . map ( |ty| ty. fold_with ( & mut type_mapper) ) ,
734791 ) ;
735792
736793 match ocx. eq ( & cause, param_env, trait_return_ty, impl_return_ty) {
@@ -787,6 +844,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
787844 }
788845 }
789846
847+ // FIXME: This has the same issue as #108544, but since this isn't breaking
848+ // existing code, I'm not particularly inclined to do the same hack as above
849+ // where we process wf obligations manually. This can be fixed in a forward-
850+ // compatible way later.
851+ let collected_types = collector. types ;
852+ for ( _, & ( ty, _) ) in & collected_types {
853+ ocx. register_obligation ( traits:: Obligation :: new (
854+ tcx,
855+ misc_cause. clone ( ) ,
856+ param_env,
857+ ty:: ClauseKind :: WellFormed ( ty. into ( ) ) ,
858+ ) ) ;
859+ }
860+
790861 // Check that all obligations are satisfied by the implementation's
791862 // RPITs.
792863 let errors = ocx. select_all_or_error ( ) ;
@@ -795,8 +866,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
795866 return Err ( reported) ;
796867 }
797868
798- let collected_types = collector. types ;
799-
800869 // Finally, resolve all regions. This catches wily misuses of
801870 // lifetime parameters.
802871 let outlives_env = OutlivesEnvironment :: with_bounds (
0 commit comments