1+ use smallvec:: SmallVec ;
2+
13use crate :: ty:: context:: TyCtxt ;
24use crate :: ty:: { self , DefId , ParamEnv , Ty } ;
35
@@ -31,27 +33,31 @@ impl<'tcx> InhabitedPredicate<'tcx> {
3133 /// Returns true if the corresponding type is inhabited in the given
3234 /// `ParamEnv` and module
3335 pub fn apply ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > , module_def_id : DefId ) -> bool {
34- let Ok ( result) = self
35- . apply_inner :: < !> ( tcx, param_env, & |id| Ok ( tcx. is_descendant_of ( module_def_id, id) ) ) ;
36+ let Ok ( result) = self . apply_inner :: < !> ( tcx, param_env, & mut Default :: default ( ) , & |id| {
37+ Ok ( tcx. is_descendant_of ( module_def_id, id) )
38+ } ) ;
3639 result
3740 }
3841
3942 /// Same as `apply`, but returns `None` if self contains a module predicate
4043 pub fn apply_any_module ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Option < bool > {
41- self . apply_inner ( tcx, param_env, & |_| Err ( ( ) ) ) . ok ( )
44+ self . apply_inner ( tcx, param_env, & mut Default :: default ( ) , & |_| Err ( ( ) ) ) . ok ( )
4245 }
4346
4447 /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
4548 /// privately uninhabited types are considered always uninhabited.
4649 pub fn apply_ignore_module ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> bool {
47- let Ok ( result) = self . apply_inner :: < !> ( tcx, param_env, & |_| Ok ( true ) ) ;
50+ let Ok ( result) =
51+ self . apply_inner :: < !> ( tcx, param_env, & mut Default :: default ( ) , & |_| Ok ( true ) ) ;
4852 result
4953 }
5054
51- fn apply_inner < E > (
55+ #[ instrument( level = "debug" , skip( tcx, param_env, in_module) , ret) ]
56+ fn apply_inner < E : std:: fmt:: Debug > (
5257 self ,
5358 tcx : TyCtxt < ' tcx > ,
5459 param_env : ParamEnv < ' tcx > ,
60+ eval_stack : & mut SmallVec < [ Ty < ' tcx > ; 1 ] > , // for cycle detection
5561 in_module : & impl Fn ( DefId ) -> Result < bool , E > ,
5662 ) -> Result < bool , E > {
5763 match self {
@@ -71,11 +77,25 @@ impl<'tcx> InhabitedPredicate<'tcx> {
7177 match normalized_pred {
7278 // We don't have more information than we started with, so consider inhabited.
7379 Self :: GenericType ( _) => Ok ( true ) ,
74- pred => pred. apply_inner ( tcx, param_env, in_module) ,
80+ pred => {
81+ // A type which is cyclic when monomorphized can happen here since the
82+ // layout error would only trigger later. See e.g. `tests/ui/sized/recursive-type-2.rs`.
83+ if eval_stack. contains ( & t) {
84+ return Ok ( true ) ; // Recover; this will error later.
85+ }
86+ eval_stack. push ( t) ;
87+ let ret = pred. apply_inner ( tcx, param_env, eval_stack, in_module) ;
88+ eval_stack. pop ( ) ;
89+ ret
90+ }
7591 }
7692 }
77- Self :: And ( [ a, b] ) => try_and ( a, b, |x| x. apply_inner ( tcx, param_env, in_module) ) ,
78- Self :: Or ( [ a, b] ) => try_or ( a, b, |x| x. apply_inner ( tcx, param_env, in_module) ) ,
93+ Self :: And ( [ a, b] ) => {
94+ try_and ( a, b, |x| x. apply_inner ( tcx, param_env, eval_stack, in_module) )
95+ }
96+ Self :: Or ( [ a, b] ) => {
97+ try_or ( a, b, |x| x. apply_inner ( tcx, param_env, eval_stack, in_module) )
98+ }
7999 }
80100 }
81101
@@ -197,7 +217,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
197217
198218// this is basically like `f(a)? && f(b)?` but different in the case of
199219// `Ok(false) && Err(_) -> Ok(false)`
200- fn try_and < T , E > ( a : T , b : T , f : impl Fn ( T ) -> Result < bool , E > ) -> Result < bool , E > {
220+ fn try_and < T , E > ( a : T , b : T , mut f : impl FnMut ( T ) -> Result < bool , E > ) -> Result < bool , E > {
201221 let a = f ( a) ;
202222 if matches ! ( a, Ok ( false ) ) {
203223 return Ok ( false ) ;
@@ -209,7 +229,7 @@ fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E
209229 }
210230}
211231
212- fn try_or < T , E > ( a : T , b : T , f : impl Fn ( T ) -> Result < bool , E > ) -> Result < bool , E > {
232+ fn try_or < T , E > ( a : T , b : T , mut f : impl FnMut ( T ) -> Result < bool , E > ) -> Result < bool , E > {
213233 let a = f ( a) ;
214234 if matches ! ( a, Ok ( true ) ) {
215235 return Ok ( true ) ;
0 commit comments