11use rustc_data_structures:: fx:: FxHashSet ;
2+ use rustc_data_structures:: stack:: ensure_sufficient_stack;
23use rustc_middle:: ty:: visit:: { TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
34use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
45use rustc_span:: Span ;
@@ -27,12 +28,13 @@ impl From<ty::ParamConst> for Parameter {
2728
2829/// Returns the set of parameters constrained by the impl header.
2930pub fn parameters_for_impl < ' tcx > (
31+ tcx : TyCtxt < ' tcx > ,
3032 impl_self_ty : Ty < ' tcx > ,
3133 impl_trait_ref : Option < ty:: TraitRef < ' tcx > > ,
3234) -> FxHashSet < Parameter > {
3335 let vec = match impl_trait_ref {
34- Some ( tr) => parameters_for ( & tr, false ) ,
35- None => parameters_for ( & impl_self_ty, false ) ,
36+ Some ( tr) => parameters_for ( tcx , & tr, false ) ,
37+ None => parameters_for ( tcx , & impl_self_ty, false ) ,
3638 } ;
3739 vec. into_iter ( ) . collect ( )
3840}
@@ -43,26 +45,43 @@ pub fn parameters_for_impl<'tcx>(
4345/// of parameters whose values are needed in order to constrain `ty` - these
4446/// differ, with the latter being a superset, in the presence of projections.
4547pub fn parameters_for < ' tcx > (
48+ tcx : TyCtxt < ' tcx > ,
4649 t : & impl TypeVisitable < TyCtxt < ' tcx > > ,
4750 include_nonconstraining : bool ,
4851) -> Vec < Parameter > {
49- let mut collector = ParameterCollector { parameters : vec ! [ ] , include_nonconstraining } ;
52+ let mut collector =
53+ ParameterCollector { tcx, parameters : vec ! [ ] , include_nonconstraining, depth : 0 } ;
5054 t. visit_with ( & mut collector) ;
5155 collector. parameters
5256}
5357
54- struct ParameterCollector {
58+ struct ParameterCollector < ' tcx > {
59+ tcx : TyCtxt < ' tcx > ,
5560 parameters : Vec < Parameter > ,
5661 include_nonconstraining : bool ,
62+ depth : usize ,
5763}
5864
59- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for ParameterCollector {
65+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for ParameterCollector < ' tcx > {
6066 fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
6167 match * t. kind ( ) {
62- ty:: Alias ( ..) if !self . include_nonconstraining => {
63- // projections are not injective
68+ ty:: Alias ( ty:: Projection | ty:: Inherent | ty:: Opaque , _)
69+ if !self . include_nonconstraining =>
70+ {
71+ // Projections are not injective in general.
6472 return ControlFlow :: Continue ( ( ) ) ;
6573 }
74+ ty:: Alias ( ty:: Weak , alias) if !self . include_nonconstraining => {
75+ if !self . tcx . recursion_limit ( ) . value_within_limit ( self . depth ) {
76+ // Other constituent types may still constrain some generic params, consider
77+ // `<T> (Overflow, T)` for example. Therefore we want to continue instead of
78+ // breaking. Only affects diagnostics.
79+ return ControlFlow :: Continue ( ( ) ) ;
80+ }
81+ self . depth += 1 ;
82+ let ty = self . tcx . type_of ( alias. def_id ) . instantiate ( self . tcx , alias. args ) ;
83+ return ensure_sufficient_stack ( || ty. visit_with ( self ) ) ;
84+ }
6685 ty:: Param ( data) => {
6786 self . parameters . push ( Parameter :: from ( data) ) ;
6887 }
@@ -82,7 +101,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
82101 fn visit_const ( & mut self , c : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
83102 match c. kind ( ) {
84103 ty:: ConstKind :: Unevaluated ( ..) if !self . include_nonconstraining => {
85- // Constant expressions are not injective
104+ // Constant expressions are not injective in general.
86105 return c. ty ( ) . visit_with ( self ) ;
87106 }
88107 ty:: ConstKind :: Param ( data) => {
@@ -201,12 +220,12 @@ pub fn setup_constraining_predicates<'tcx>(
201220 // `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
202221 // Then the projection only applies if `T` is known, but it still
203222 // does not determine `U`.
204- let inputs = parameters_for ( & projection. projection_ty , true ) ;
223+ let inputs = parameters_for ( tcx , & projection. projection_ty , true ) ;
205224 let relies_only_on_inputs = inputs. iter ( ) . all ( |p| input_parameters. contains ( p) ) ;
206225 if !relies_only_on_inputs {
207226 continue ;
208227 }
209- input_parameters. extend ( parameters_for ( & projection. term , false ) ) ;
228+ input_parameters. extend ( parameters_for ( tcx , & projection. term , false ) ) ;
210229 } else {
211230 continue ;
212231 }
0 commit comments