@@ -15,12 +15,14 @@ use rustc_hir::{
1515} ;
1616use rustc_hir_analysis:: hir_ty_to_ty;
1717use 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 ;
2019use rustc_middle:: ty:: adjustment:: Adjust ;
21- use rustc_middle:: ty:: { self , Ty } ;
20+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
2221use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
2322use 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 ;
2426
2527// FIXME: this is a correctness problem but there's no suitable
2628// warn-by-default category.
@@ -141,21 +143,35 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
141143
142144fn is_value_unfrozen_raw < ' tcx > (
143145 cx : & LateContext < ' tcx > ,
144- result : Result < ConstValue < ' tcx > , ErrorHandled > ,
146+ result : Result < Option < ty :: ValTree < ' tcx > > , ErrorHandled > ,
145147 ty : Ty < ' tcx > ,
146148) -> 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 ( ) {
149151 // the fact that we have to dig into every structs to search enums
150152 // leads us to the point checking `UnsafeCell` directly is the only option.
151153 ty:: Adt ( ty_def, ..) if ty_def. is_unsafe_cell ( ) => true ,
152154 // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the
153155 // contained value.
154156 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) )
158159 } ,
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) ) ,
159175 _ => false ,
160176 }
161177 }
@@ -184,24 +200,44 @@ fn is_value_unfrozen_raw<'tcx>(
184200 // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
185201 err == ErrorHandled :: TooGeneric
186202 } ,
187- |val| inner ( cx, mir :: ConstantKind :: from_value ( val, ty) ) ,
203+ |val| val . map_or ( true , |val| inner ( cx, val, ty) ) ,
188204 )
189205}
190206
191207fn 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 ) ;
193214 is_value_unfrozen_raw ( cx, result, ty)
194215}
195216
196217fn is_value_unfrozen_expr < ' tcx > ( cx : & LateContext < ' tcx > , hir_id : HirId , def_id : DefId , ty : Ty < ' tcx > ) -> bool {
197218 let substs = cx. typeck_results ( ) . node_substs ( hir_id) ;
198219
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 ) ;
202221 is_value_unfrozen_raw ( cx, result, ty)
203222}
204223
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+
205241#[ derive( Copy , Clone ) ]
206242enum Source {
207243 Item { item : Span } ,
0 commit comments