3
3
use std:: convert:: TryFrom ;
4
4
5
5
use rustc_hir:: Mutability ;
6
- use rustc_middle:: ty :: layout :: HasTyCtxt ;
6
+ use rustc_middle:: mir ;
7
7
use rustc_middle:: ty:: { self , TyCtxt } ;
8
- use rustc_middle:: {
9
- mir:: { self , interpret:: ConstAlloc } ,
10
- ty:: ScalarInt ,
11
- } ;
12
8
use rustc_span:: { source_map:: DUMMY_SP , symbol:: Symbol } ;
13
- use rustc_target:: abi:: VariantIdx ;
14
9
15
10
use 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 ,
18
13
} ;
19
14
20
15
mod error;
21
16
mod eval_queries;
22
17
mod fn_queries;
23
18
mod machine;
19
+ mod valtrees;
24
20
25
21
pub use error:: * ;
26
22
pub use eval_queries:: * ;
27
23
pub use fn_queries:: * ;
28
24
pub use machine:: * ;
25
+ pub ( crate ) use valtrees:: { const_to_valtree, valtree_to_const_value} ;
29
26
30
27
pub ( crate ) fn const_caller_location (
31
28
tcx : TyCtxt < ' _ > ,
@@ -41,128 +38,6 @@ pub(crate) fn const_caller_location(
41
38
ConstValue :: Scalar ( Scalar :: from_maybe_pointer ( loc_place. ptr , & tcx) )
42
39
}
43
40
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
-
166
41
/// This function should never fail for validated constants. However, it is also invoked from the
167
42
/// pretty printer which might attempt to format invalid constants and in that case it might fail.
168
43
pub ( crate ) fn try_destructure_const < ' tcx > (
@@ -202,6 +77,7 @@ pub(crate) fn try_destructure_const<'tcx>(
202
77
Ok ( mir:: DestructuredConst { variant, fields } )
203
78
}
204
79
80
+ #[ instrument( skip( tcx) , level = "debug" ) ]
205
81
pub ( crate ) fn deref_const < ' tcx > (
206
82
tcx : TyCtxt < ' tcx > ,
207
83
param_env : ty:: ParamEnv < ' tcx > ,
0 commit comments