33use std:: convert:: TryFrom ;
44
55use rustc_hir:: Mutability ;
6- use rustc_middle:: ty :: layout :: HasTyCtxt ;
6+ use rustc_middle:: mir ;
77use rustc_middle:: ty:: { self , TyCtxt } ;
8- use rustc_middle:: {
9- mir:: { self , interpret:: ConstAlloc } ,
10- ty:: ScalarInt ,
11- } ;
128use rustc_span:: { source_map:: DUMMY_SP , symbol:: Symbol } ;
13- use rustc_target:: abi:: VariantIdx ;
149
1510use crate :: interpret:: {
16- intern_const_alloc_recursive, ConstValue , InternKind , InterpCx , InterpResult , MPlaceTy ,
17- MemPlaceMeta , Scalar ,
11+ intern_const_alloc_recursive, ConstValue , InternKind , InterpCx , InterpResult , MemPlaceMeta ,
12+ Scalar ,
1813} ;
1914
2015mod error;
2116mod eval_queries;
2217mod fn_queries;
2318mod machine;
19+ mod valtrees;
2420
2521pub use error:: * ;
2622pub use eval_queries:: * ;
2723pub use fn_queries:: * ;
2824pub use machine:: * ;
25+ pub ( crate ) use valtrees:: { const_to_valtree, valtree_to_const_value} ;
2926
3027pub ( crate ) fn const_caller_location (
3128 tcx : TyCtxt < ' _ > ,
@@ -41,128 +38,6 @@ pub(crate) fn const_caller_location(
4138 ConstValue :: Scalar ( Scalar :: from_maybe_pointer ( loc_place. ptr , & tcx) )
4239}
4340
44- /// Convert an evaluated constant to a type level constant
45- pub ( crate ) fn const_to_valtree < ' tcx > (
46- tcx : TyCtxt < ' tcx > ,
47- param_env : ty:: ParamEnv < ' tcx > ,
48- raw : ConstAlloc < ' tcx > ,
49- ) -> Option < ty:: ValTree < ' tcx > > {
50- let ecx = mk_eval_cx (
51- tcx, DUMMY_SP , param_env,
52- // It is absolutely crucial for soundness that
53- // we do not read from static items or other mutable memory.
54- false ,
55- ) ;
56- let place = ecx. raw_const_to_mplace ( raw) . unwrap ( ) ;
57- const_to_valtree_inner ( & ecx, & place)
58- }
59-
60- #[ instrument( skip( ecx) , level = "debug" ) ]
61- fn branches < ' tcx > (
62- ecx : & CompileTimeEvalContext < ' tcx , ' tcx > ,
63- place : & MPlaceTy < ' tcx > ,
64- n : usize ,
65- variant : Option < VariantIdx > ,
66- ) -> Option < ty:: ValTree < ' tcx > > {
67- let place = match variant {
68- Some ( variant) => ecx. mplace_downcast ( & place, variant) . unwrap ( ) ,
69- None => * place,
70- } ;
71- let variant = variant. map ( |variant| Some ( ty:: ValTree :: Leaf ( ScalarInt :: from ( variant. as_u32 ( ) ) ) ) ) ;
72- debug ! ( ?place, ?variant) ;
73-
74- let fields = ( 0 ..n) . map ( |i| {
75- let field = ecx. mplace_field ( & place, i) . unwrap ( ) ;
76- const_to_valtree_inner ( ecx, & field)
77- } ) ;
78- // For enums, we prepend their variant index before the variant's fields so we can figure out
79- // the variant again when just seeing a valtree.
80- let branches = variant. into_iter ( ) . chain ( fields) ;
81- Some ( ty:: ValTree :: Branch ( ecx. tcx . arena . alloc_from_iter ( branches. collect :: < Option < Vec < _ > > > ( ) ?) ) )
82- }
83-
84- fn slice_branches < ' tcx > (
85- ecx : & CompileTimeEvalContext < ' tcx , ' tcx > ,
86- place : & MPlaceTy < ' tcx > ,
87- ) -> Option < ty:: ValTree < ' tcx > > {
88- let n = place. len ( & ecx. tcx ( ) ) . expect ( & format ! ( "expected to use len of place {:?}" , place) ) ;
89- let branches = ( 0 ..n) . map ( |i| {
90- let place_elem = ecx. mplace_index ( place, i) . unwrap ( ) ;
91- const_to_valtree_inner ( ecx, & place_elem)
92- } ) ;
93-
94- Some ( ty:: ValTree :: Branch ( ecx. tcx . arena . alloc_from_iter ( branches. collect :: < Option < Vec < _ > > > ( ) ?) ) )
95- }
96-
97- #[ instrument( skip( ecx) , level = "debug" ) ]
98- fn const_to_valtree_inner < ' tcx > (
99- ecx : & CompileTimeEvalContext < ' tcx , ' tcx > ,
100- place : & MPlaceTy < ' tcx > ,
101- ) -> Option < ty:: ValTree < ' tcx > > {
102- match place. layout . ty . kind ( ) {
103- ty:: FnDef ( ..) => Some ( ty:: ValTree :: zst ( ) ) ,
104- ty:: Bool | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Char => {
105- let val = ecx. read_immediate ( & place. into ( ) ) . unwrap ( ) ;
106- let val = val. to_scalar ( ) . unwrap ( ) ;
107- Some ( ty:: ValTree :: Leaf ( val. assert_int ( ) ) )
108- }
109-
110- // Raw pointers are not allowed in type level constants, as we cannot properly test them for
111- // equality at compile-time (see `ptr_guaranteed_eq`/`_ne`).
112- // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
113- // agree with runtime equality tests.
114- ty:: FnPtr ( _) | ty:: RawPtr ( _) => None ,
115-
116- ty:: Ref ( _, _, _) => {
117- let derefd_place = ecx. deref_operand ( & place. into ( ) ) . unwrap_or_else ( |e| bug ! ( "couldn't deref {:?}, error: {:?}" , place, e) ) ;
118- debug ! ( ?derefd_place) ;
119-
120- const_to_valtree_inner ( ecx, & derefd_place)
121- }
122-
123- ty:: Str | ty:: Slice ( _) | ty:: Array ( _, _) => {
124- let valtree = slice_branches ( ecx, place) ;
125- debug ! ( ?valtree) ;
126-
127- valtree
128- }
129- // Trait objects are not allowed in type level constants, as we have no concept for
130- // resolving their backing type, even if we can do that at const eval time. We may
131- // hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
132- // but it is unclear if this is useful.
133- ty:: Dynamic ( ..) => None ,
134-
135- ty:: Tuple ( substs) => branches ( ecx, place, substs. len ( ) , None ) ,
136-
137- ty:: Adt ( def, _) => {
138- if def. variants ( ) . is_empty ( ) {
139- bug ! ( "uninhabited types should have errored and never gotten converted to valtree" )
140- }
141-
142- let variant = ecx. read_discriminant ( & place. into ( ) ) . unwrap ( ) . 1 ;
143-
144- branches ( ecx, place, def. variant ( variant) . fields . len ( ) , def. is_enum ( ) . then_some ( variant) )
145- }
146-
147- ty:: Never
148- | ty:: Error ( _)
149- | ty:: Foreign ( ..)
150- | ty:: Infer ( ty:: FreshIntTy ( _) )
151- | ty:: Infer ( ty:: FreshFloatTy ( _) )
152- | ty:: Projection ( ..)
153- | ty:: Param ( _)
154- | ty:: Bound ( ..)
155- | ty:: Placeholder ( ..)
156- // FIXME(oli-obk): we could look behind opaque types
157- | ty:: Opaque ( ..)
158- | ty:: Infer ( _)
159- // FIXME(oli-obk): we can probably encode closures just like structs
160- | ty:: Closure ( ..)
161- | ty:: Generator ( ..)
162- | ty:: GeneratorWitness ( ..) => None ,
163- }
164- }
165-
16641/// This function should never fail for validated constants. However, it is also invoked from the
16742/// pretty printer which might attempt to format invalid constants and in that case it might fail.
16843pub ( crate ) fn try_destructure_const < ' tcx > (
@@ -202,6 +77,7 @@ pub(crate) fn try_destructure_const<'tcx>(
20277 Ok ( mir:: DestructuredConst { variant, fields } )
20378}
20479
80+ #[ instrument( skip( tcx) , level = "debug" ) ]
20581pub ( crate ) fn deref_const < ' tcx > (
20682 tcx : TyCtxt < ' tcx > ,
20783 param_env : ty:: ParamEnv < ' tcx > ,
0 commit comments