@@ -15,12 +15,14 @@ use rustc_hir::{
15
15
} ;
16
16
use rustc_hir_analysis:: hir_ty_to_ty;
17
17
use rustc_lint:: { LateContext , LateLintPass , Lint } ;
18
- use rustc_middle:: mir;
19
- use rustc_middle:: mir:: interpret:: { ConstValue , ErrorHandled } ;
18
+ use rustc_middle:: mir:: interpret:: ErrorHandled ;
20
19
use rustc_middle:: ty:: adjustment:: Adjust ;
21
- use rustc_middle:: ty:: { self , Ty } ;
20
+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
22
21
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
23
22
use rustc_span:: { sym, InnerSpan , Span } ;
23
+ use rustc_target:: abi:: VariantIdx ;
24
+ use rustc_middle:: mir:: interpret:: EvalToValTreeResult ;
25
+ use rustc_middle:: mir:: interpret:: GlobalId ;
24
26
25
27
// FIXME: this is a correctness problem but there's no suitable
26
28
// warn-by-default category.
@@ -141,21 +143,35 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
141
143
142
144
fn is_value_unfrozen_raw < ' tcx > (
143
145
cx : & LateContext < ' tcx > ,
144
- result : Result < ConstValue < ' tcx > , ErrorHandled > ,
146
+ result : Result < Option < ty :: ValTree < ' tcx > > , ErrorHandled > ,
145
147
ty : Ty < ' tcx > ,
146
148
) -> bool {
147
- fn inner < ' tcx > ( cx : & LateContext < ' tcx > , val : mir :: ConstantKind < ' tcx > ) -> bool {
148
- match val . ty ( ) . kind ( ) {
149
+ fn inner < ' tcx > ( cx : & LateContext < ' tcx > , val : ty :: ValTree < ' tcx > , ty : Ty < ' tcx > ) -> bool {
150
+ match * ty . kind ( ) {
149
151
// the fact that we have to dig into every structs to search enums
150
152
// leads us to the point checking `UnsafeCell` directly is the only option.
151
153
ty:: Adt ( ty_def, ..) if ty_def. is_unsafe_cell ( ) => true ,
152
154
// As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the
153
155
// contained value.
154
156
ty:: Adt ( def, ..) if def. is_union ( ) => false ,
155
- ty:: Array ( ..) | ty:: Adt ( ..) | ty:: Tuple ( ..) => {
156
- let val = cx. tcx . destructure_mir_constant ( cx. param_env , val) ;
157
- val. fields . iter ( ) . any ( |field| inner ( cx, * field) )
157
+ ty:: Array ( ty, _) => {
158
+ val. unwrap_branch ( ) . iter ( ) . any ( |field| inner ( cx, * field, ty) )
158
159
} ,
160
+ ty:: Adt ( def, _) if def. is_union ( ) => false ,
161
+ ty:: Adt ( def, substs) if def. is_enum ( ) => {
162
+ let ( & variant_index, fields) = val. unwrap_branch ( ) . split_first ( ) . unwrap ( ) ;
163
+ let variant_index =
164
+ VariantIdx :: from_u32 ( variant_index. unwrap_leaf ( ) . try_to_u32 ( ) . ok ( ) . unwrap ( ) ) ;
165
+ fields. iter ( ) . copied ( ) . zip (
166
+ def. variants ( ) [ variant_index]
167
+ . fields
168
+ . iter ( )
169
+ . map ( |field| field. ty ( cx. tcx , substs) ) ) . any ( |( field, ty) | inner ( cx, field, ty) )
170
+ }
171
+ ty:: Adt ( def, substs) => {
172
+ val. unwrap_branch ( ) . iter ( ) . zip ( def. non_enum_variant ( ) . fields . iter ( ) . map ( |field| field. ty ( cx. tcx , substs) ) ) . any ( |( field, ty) | inner ( cx, * field, ty) )
173
+ }
174
+ ty:: Tuple ( tys) => val. unwrap_branch ( ) . iter ( ) . zip ( tys) . any ( |( field, ty) | inner ( cx, * field, ty) ) ,
159
175
_ => false ,
160
176
}
161
177
}
@@ -184,24 +200,44 @@ fn is_value_unfrozen_raw<'tcx>(
184
200
// I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
185
201
err == ErrorHandled :: TooGeneric
186
202
} ,
187
- |val| inner ( cx, mir :: ConstantKind :: from_value ( val, ty) ) ,
203
+ |val| val . map_or ( true , |val| inner ( cx, val, ty) ) ,
188
204
)
189
205
}
190
206
191
207
fn is_value_unfrozen_poly < ' tcx > ( cx : & LateContext < ' tcx > , body_id : BodyId , ty : Ty < ' tcx > ) -> bool {
192
- let result = cx. tcx . const_eval_poly ( body_id. hir_id . owner . to_def_id ( ) ) ;
208
+ let def_id = body_id. hir_id . owner . to_def_id ( ) ;
209
+ let substs = ty:: InternalSubsts :: identity_for_item ( cx. tcx , def_id) ;
210
+ let instance = ty:: Instance :: new ( def_id, substs) ;
211
+ let cid = rustc_middle:: mir:: interpret:: GlobalId { instance, promoted : None } ;
212
+ let param_env = cx. tcx . param_env ( def_id) . with_reveal_all_normalized ( cx. tcx ) ;
213
+ let result = cx. tcx . const_eval_global_id_for_typeck ( param_env, cid, None ) ;
193
214
is_value_unfrozen_raw ( cx, result, ty)
194
215
}
195
216
196
217
fn is_value_unfrozen_expr < ' tcx > ( cx : & LateContext < ' tcx > , hir_id : HirId , def_id : DefId , ty : Ty < ' tcx > ) -> bool {
197
218
let substs = cx. typeck_results ( ) . node_substs ( hir_id) ;
198
219
199
- let result = cx
200
- . tcx
201
- . const_eval_resolve ( cx. param_env , mir:: UnevaluatedConst :: new ( def_id, substs) , None ) ;
220
+ let result = const_eval_resolve ( cx. tcx , cx. param_env , ty:: UnevaluatedConst :: new ( def_id, substs) , None ) ;
202
221
is_value_unfrozen_raw ( cx, result, ty)
203
222
}
204
223
224
+
225
+ pub fn const_eval_resolve < ' tcx > (
226
+ tcx : TyCtxt < ' tcx > ,
227
+ param_env : ty:: ParamEnv < ' tcx > ,
228
+ ct : ty:: UnevaluatedConst < ' tcx > ,
229
+ span : Option < Span > ,
230
+ ) -> EvalToValTreeResult < ' tcx > {
231
+ match ty:: Instance :: resolve ( tcx, param_env, ct. def , ct. substs ) {
232
+ Ok ( Some ( instance) ) => {
233
+ let cid = GlobalId { instance, promoted : None } ;
234
+ tcx. const_eval_global_id_for_typeck ( param_env, cid, span)
235
+ }
236
+ Ok ( None ) => Err ( ErrorHandled :: TooGeneric ) ,
237
+ Err ( err) => Err ( ErrorHandled :: Reported ( err. into ( ) ) ) ,
238
+ }
239
+ }
240
+
205
241
#[ derive( Copy , Clone ) ]
206
242
enum Source {
207
243
Item { item : Span } ,
0 commit comments