@@ -14,6 +14,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
14
14
use rustc_infer:: infer:: { self , InferCtxt , TyCtxtInferExt } ;
15
15
use rustc_infer:: traits:: util;
16
16
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
17
+ use rustc_middle:: ty:: fold:: BottomUpFolder ;
17
18
use rustc_middle:: ty:: util:: ExplicitSelf ;
18
19
use rustc_middle:: ty:: {
19
20
self , GenericArgs , Ty , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitableExt ,
@@ -692,9 +693,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
692
693
let ocx = ObligationCtxt :: new ( infcx) ;
693
694
694
695
// 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) ;
696
697
let impl_sig = ocx. normalize (
697
- & norm_cause ,
698
+ & misc_cause ,
698
699
param_env,
699
700
tcx. liberate_late_bound_regions (
700
701
impl_m. def_id ,
@@ -725,12 +726,68 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
725
726
) ;
726
727
}
727
728
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) ;
729
730
trait_sig. error_reported ( ) ?;
730
731
let trait_return_ty = trait_sig. output ( ) ;
731
732
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
+ } ;
732
785
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) ) ,
734
791
) ;
735
792
736
793
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>(
787
844
}
788
845
}
789
846
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
+
790
861
// Check that all obligations are satisfied by the implementation's
791
862
// RPITs.
792
863
let errors = ocx. select_all_or_error ( ) ;
@@ -795,8 +866,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
795
866
return Err ( reported) ;
796
867
}
797
868
798
- let collected_types = collector. types ;
799
-
800
869
// Finally, resolve all regions. This catches wily misuses of
801
870
// lifetime parameters.
802
871
let outlives_env = OutlivesEnvironment :: with_bounds (
0 commit comments