1
1
use smallvec:: SmallVec ;
2
2
3
3
use crate :: ty:: context:: TyCtxt ;
4
- use crate :: ty:: { self , DefId , ParamEnv , Ty } ;
4
+ use crate :: ty:: { self , DefId , OpaqueTypeKey , ParamEnv , Ty } ;
5
5
6
6
/// Represents whether some type is inhabited in a given context.
7
7
/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
@@ -23,42 +23,62 @@ pub enum InhabitedPredicate<'tcx> {
23
23
/// Inhabited if some generic type is inhabited.
24
24
/// These are replaced by calling [`Self::instantiate`].
25
25
GenericType ( Ty < ' tcx > ) ,
26
+ /// Inhabited if either we don't know the hidden type or we know it and it is inhabited.
27
+ OpaqueType ( OpaqueTypeKey < ' tcx > ) ,
26
28
/// A AND B
27
29
And ( & ' tcx [ InhabitedPredicate < ' tcx > ; 2 ] ) ,
28
30
/// A OR B
29
31
Or ( & ' tcx [ InhabitedPredicate < ' tcx > ; 2 ] ) ,
30
32
}
31
33
32
34
impl < ' tcx > InhabitedPredicate < ' tcx > {
33
- /// Returns true if the corresponding type is inhabited in the given
34
- /// `ParamEnv` and module
35
+ /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module.
35
36
pub fn apply ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > , module_def_id : DefId ) -> bool {
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
- } ) ;
37
+ self . apply_revealing_opaque ( tcx, param_env, module_def_id, & |_| None )
38
+ }
39
+
40
+ /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module,
41
+ /// revealing opaques when possible.
42
+ pub fn apply_revealing_opaque (
43
+ self ,
44
+ tcx : TyCtxt < ' tcx > ,
45
+ param_env : ParamEnv < ' tcx > ,
46
+ module_def_id : DefId ,
47
+ reveal_opaque : & impl Fn ( OpaqueTypeKey < ' tcx > ) -> Option < Ty < ' tcx > > ,
48
+ ) -> bool {
49
+ let Ok ( result) = self . apply_inner :: < !> (
50
+ tcx,
51
+ param_env,
52
+ & mut Default :: default ( ) ,
53
+ & |id| Ok ( tcx. is_descendant_of ( module_def_id, id) ) ,
54
+ reveal_opaque,
55
+ ) ;
39
56
result
40
57
}
41
58
42
59
/// Same as `apply`, but returns `None` if self contains a module predicate
43
60
pub fn apply_any_module ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Option < bool > {
44
- self . apply_inner ( tcx, param_env, & mut Default :: default ( ) , & |_| Err ( ( ) ) ) . ok ( )
61
+ self . apply_inner ( tcx, param_env, & mut Default :: default ( ) , & |_| Err ( ( ) ) , & |_| None ) . ok ( )
45
62
}
46
63
47
64
/// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
48
65
/// privately uninhabited types are considered always uninhabited.
49
66
pub fn apply_ignore_module ( self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> bool {
50
67
let Ok ( result) =
51
- self . apply_inner :: < !> ( tcx, param_env, & mut Default :: default ( ) , & |_| Ok ( true ) ) ;
68
+ self . apply_inner :: < !> ( tcx, param_env, & mut Default :: default ( ) , & |_| Ok ( true ) , & |_| {
69
+ None
70
+ } ) ;
52
71
result
53
72
}
54
73
55
- #[ instrument( level = "debug" , skip( tcx, param_env, in_module) , ret) ]
74
+ #[ instrument( level = "debug" , skip( tcx, param_env, in_module, reveal_opaque ) , ret) ]
56
75
fn apply_inner < E : std:: fmt:: Debug > (
57
76
self ,
58
77
tcx : TyCtxt < ' tcx > ,
59
78
param_env : ParamEnv < ' tcx > ,
60
79
eval_stack : & mut SmallVec < [ Ty < ' tcx > ; 1 ] > , // for cycle detection
61
80
in_module : & impl Fn ( DefId ) -> Result < bool , E > ,
81
+ reveal_opaque : & impl Fn ( OpaqueTypeKey < ' tcx > ) -> Option < Ty < ' tcx > > ,
62
82
) -> Result < bool , E > {
63
83
match self {
64
84
Self :: False => Ok ( false ) ,
@@ -84,18 +104,41 @@ impl<'tcx> InhabitedPredicate<'tcx> {
84
104
return Ok ( true ) ; // Recover; this will error later.
85
105
}
86
106
eval_stack. push ( t) ;
87
- let ret = pred. apply_inner ( tcx, param_env, eval_stack, in_module) ;
107
+ let ret =
108
+ pred. apply_inner ( tcx, param_env, eval_stack, in_module, reveal_opaque) ;
88
109
eval_stack. pop ( ) ;
89
110
ret
90
111
}
91
112
}
92
113
}
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
- }
114
+ Self :: OpaqueType ( key) => match reveal_opaque ( key) {
115
+ // Unknown opaque is assumed inhabited.
116
+ None => Ok ( true ) ,
117
+ // Known opaque type is inspected recursively.
118
+ Some ( t) => {
119
+ // A cyclic opaque type can happen in corner cases that would only error later.
120
+ // See e.g. `tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs`.
121
+ if eval_stack. contains ( & t) {
122
+ return Ok ( true ) ; // Recover; this will error later.
123
+ }
124
+ eval_stack. push ( t) ;
125
+ let ret = t. inhabited_predicate ( tcx) . apply_inner (
126
+ tcx,
127
+ param_env,
128
+ eval_stack,
129
+ in_module,
130
+ reveal_opaque,
131
+ ) ;
132
+ eval_stack. pop ( ) ;
133
+ ret
134
+ }
135
+ } ,
136
+ Self :: And ( [ a, b] ) => try_and ( a, b, |x| {
137
+ x. apply_inner ( tcx, param_env, eval_stack, in_module, reveal_opaque)
138
+ } ) ,
139
+ Self :: Or ( [ a, b] ) => try_or ( a, b, |x| {
140
+ x. apply_inner ( tcx, param_env, eval_stack, in_module, reveal_opaque)
141
+ } ) ,
99
142
}
100
143
}
101
144
0 commit comments