@@ -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 ,
@@ -661,8 +662,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
661
662
let trait_m = tcx. opt_associated_item ( impl_m. trait_item_def_id . unwrap ( ) ) . unwrap ( ) ;
662
663
let impl_trait_ref =
663
664
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
-
666
665
// First, check a few of the same things as `compare_impl_method`,
667
666
// just so we don't ICE during substitution later.
668
667
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>(
688
687
let trait_to_placeholder_args =
689
688
impl_to_placeholder_args. rebase_onto ( tcx, impl_m. container_id ( tcx) , trait_to_impl_args) ;
690
689
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
+
691
703
let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
692
704
let ocx = ObligationCtxt :: new ( infcx) ;
693
705
694
706
// 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) ;
696
708
let impl_sig = ocx. normalize (
697
- & norm_cause ,
709
+ & misc_cause ,
698
710
param_env,
699
711
tcx. liberate_late_bound_regions (
700
712
impl_m. def_id ,
@@ -725,12 +737,68 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
725
737
) ;
726
738
}
727
739
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) ;
729
741
trait_sig. error_reported ( ) ?;
730
742
let trait_return_ty = trait_sig. output ( ) ;
731
743
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
+ } ;
732
796
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) ) ,
734
802
) ;
735
803
736
804
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>(
787
855
}
788
856
}
789
857
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
+
790
872
// Check that all obligations are satisfied by the implementation's
791
873
// RPITs.
792
874
let errors = ocx. select_all_or_error ( ) ;
@@ -795,8 +877,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
795
877
return Err ( reported) ;
796
878
}
797
879
798
- let collected_types = collector. types ;
799
-
800
880
// Finally, resolve all regions. This catches wily misuses of
801
881
// lifetime parameters.
802
882
let outlives_env = OutlivesEnvironment :: with_bounds (
0 commit comments