@@ -6,14 +6,14 @@ use rustc_hir::Mutability;
6
6
use rustc_middle:: ty:: { self , TyCtxt } ;
7
7
use rustc_middle:: {
8
8
mir:: { self , interpret:: ConstAlloc } ,
9
- ty:: { ScalarInt , Ty } ,
9
+ ty:: ScalarInt ,
10
10
} ;
11
11
use rustc_span:: { source_map:: DUMMY_SP , symbol:: Symbol } ;
12
12
use rustc_target:: abi:: VariantIdx ;
13
13
14
14
use crate :: interpret:: {
15
- intern_const_alloc_recursive, ConstValue , InternKind , InterpCx , InterpResult , MPlaceTy ,
16
- MemPlaceMeta , Scalar ,
15
+ intern_const_alloc_recursive, ConstValue , Immediate , InternKind , InterpCx , InterpResult ,
16
+ MPlaceTy , MemPlaceMeta , Scalar ,
17
17
} ;
18
18
19
19
mod error;
@@ -80,19 +80,28 @@ fn branches<'tcx>(
80
80
Some ( ty:: ValTree :: Branch ( ecx. tcx . arena . alloc_from_iter ( branches. collect :: < Option < Vec < _ > > > ( ) ?) ) )
81
81
}
82
82
83
+ fn slice_branches < ' tcx > (
84
+ ecx : & CompileTimeEvalContext < ' tcx , ' tcx > ,
85
+ place : & MPlaceTy < ' tcx > ,
86
+ n : u64 ,
87
+ ) -> Option < ty:: ValTree < ' tcx > > {
88
+ let elems = ( 0 ..n) . map ( |i| {
89
+ let place_elem = ecx. mplace_index ( place, i) . unwrap ( ) ;
90
+ const_to_valtree_inner ( ecx, & place_elem)
91
+ } ) ;
92
+
93
+ // Need `len` for the ValTree -> ConstValue conversion
94
+ let len = Some ( Some ( ty:: ValTree :: Leaf ( ScalarInt :: from ( n) ) ) ) ;
95
+ let branches = len. into_iter ( ) . chain ( elems) ;
96
+
97
+ Some ( ty:: ValTree :: Branch ( ecx. tcx . arena . alloc_from_iter ( branches. collect :: < Option < Vec < _ > > > ( ) ?) ) )
98
+ }
99
+
83
100
#[ instrument( skip( ecx) , level = "debug" ) ]
84
101
fn const_to_valtree_inner < ' tcx > (
85
102
ecx : & CompileTimeEvalContext < ' tcx , ' tcx > ,
86
103
place : & MPlaceTy < ' tcx > ,
87
104
) -> Option < ty:: ValTree < ' tcx > > {
88
- // We only want to use raw bytes in ValTrees for string slices or &[<integer_ty>]
89
- let use_bytes_for_ref = |ty : Ty < ' tcx > | -> bool {
90
- match ty. kind ( ) {
91
- ty:: Str | ty:: Char | ty:: Uint ( _) | ty:: Int ( _) | ty:: Bool => true ,
92
- _ => false ,
93
- }
94
- } ;
95
-
96
105
match place. layout . ty . kind ( ) {
97
106
ty:: FnDef ( ..) => Some ( ty:: ValTree :: zst ( ) ) ,
98
107
ty:: Bool | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Char => {
@@ -107,75 +116,52 @@ fn const_to_valtree_inner<'tcx>(
107
116
// agree with runtime equality tests.
108
117
ty:: FnPtr ( _) | ty:: RawPtr ( _) => None ,
109
118
110
- ty:: Ref ( _, ref_ty, _) if place. layout . ty . is_slice ( ) => {
111
- match ecx. try_read_immediate_from_mplace ( & place) {
112
- Ok ( Some ( imm) ) => {
113
- // `imm` is a ScalarPair. We try to get the underlying bytes behind that
114
- // fat pointer for string slices and slices of integer types. For any other
115
- // slice types we use `branches` to recursively construct the Valtree.
116
-
117
- if use_bytes_for_ref ( * ref_ty) {
118
- let ( alloc, range) = ecx. get_alloc_from_imm_scalar_pair ( imm) ;
119
- let alloc_bytes = match alloc. get_bytes ( & ecx. tcx , range) {
120
- Ok ( bytes) => bytes,
121
- Err ( _e) => return None ,
122
- } ;
123
- debug ! ( ?alloc_bytes) ;
124
-
125
- let bytes = ecx. tcx . arena . alloc_slice ( alloc_bytes) ;
126
- let len = bytes. len ( ) ;
127
- debug ! ( ?bytes, ?len) ;
128
-
129
- let slice = ty:: ValSlice { bytes} ;
130
-
131
- Some ( ty:: ValTree :: SliceOrStr ( slice) )
132
- } else {
133
- let derefd = ecx. deref_operand ( & imm. into ( ) ) . expect ( & format ! ( "couldnt deref {:?}" , imm) ) ;
134
- debug ! ( "derefd: {:?}" , derefd) ;
135
-
136
- let derefd_imm = match ecx. try_read_immediate_from_mplace ( & derefd) {
137
- Ok ( Some ( imm) ) => imm,
138
- _ => return None ,
139
- } ;
140
- debug ! ( ?derefd_imm) ;
141
-
142
- let tcx = ecx. tcx . tcx ;
143
- let scalar_len= derefd. meta . unwrap_meta ( ) ;
144
- let len = match scalar_len {
145
- Scalar :: Int ( int) => {
146
- int. try_to_machine_usize ( tcx) . expect ( & format ! ( "Expected a valid ScalarInt in {:?}" , scalar_len) )
147
- }
148
- _ => bug ! ( "expected a ScalarInt in meta data for {:?}" , place) ,
149
- } ;
150
- debug ! ( ?len) ;
151
-
152
- let valtree = branches ( ecx, place, len. try_into ( ) . expect ( "BLA" ) , None ) ;
153
- debug ! ( ?valtree) ;
154
-
155
- valtree
119
+ ty:: Ref ( _, inner_ty, _) => {
120
+ match inner_ty. kind ( ) {
121
+ ty:: Slice ( _) | ty:: Str => {
122
+ match ecx. try_read_immediate_from_mplace ( & place) {
123
+ Ok ( Some ( imm) ) => {
124
+ let mplace_ref = ecx. ref_to_mplace ( & imm) . unwrap ( ) ;
125
+ let derefd = ecx. deref_operand ( & place. into ( ) ) . expect ( & format ! ( "couldnt deref {:?}" , imm) ) ;
126
+ debug ! ( ?mplace_ref, ?derefd) ;
127
+
128
+ let len = match imm. imm {
129
+ Immediate :: ScalarPair ( _, b) => {
130
+ let len = b. to_machine_usize ( & ecx. tcx . tcx ) . unwrap ( ) ;
131
+ len
132
+ }
133
+ _ => bug ! ( "expected ScalarPair for &[T] or &str" ) ,
134
+ } ;
135
+ debug ! ( ?len) ;
136
+
137
+ let valtree = slice_branches ( ecx, & derefd, len) ;
138
+ debug ! ( ?valtree) ;
139
+
140
+ valtree
141
+ }
142
+ _ => {
143
+ None
144
+ }
156
145
}
157
146
}
158
147
_ => {
159
- None
160
- }
161
- }
162
- }
148
+ let imm = ecx. try_read_immediate_from_mplace ( & place) . unwrap_or_else ( |e| bug ! ( "couldnt read immediate from {:?}, error: {:?}" , place, e) ) ;
163
149
164
- ty:: Ref ( _, inner_ty, _) => {
165
- debug ! ( "Ref with inner_ty: {:?}" , inner_ty) ;
166
- let imm = ecx. try_read_immediate_from_mplace ( & place) . unwrap_or_else ( |e| bug ! ( "couldnt read immediate from {:?}, error: {:?}" , place, e) ) ;
167
- match imm {
168
- Some ( imm) => {
169
- debug ! ( ?imm) ;
150
+ match imm {
151
+ Some ( imm) => {
152
+ debug ! ( ?imm) ;
170
153
171
- let derefd_place = ecx. deref_mplace ( place) . unwrap_or_else ( |e| bug ! ( "couldn't deref {:?}, error: {:?}" , place, e) ) ;
172
- debug ! ( ?derefd_place) ;
154
+ let derefd_place = ecx. deref_operand ( & place. into ( ) ) . unwrap_or_else ( |e| bug ! ( "couldn't deref {:?}, error: {:?}" , place, e) ) ;
155
+ debug ! ( ?derefd_place) ;
173
156
174
- const_to_valtree_inner ( ecx, & derefd_place)
157
+ const_to_valtree_inner ( ecx, & derefd_place)
158
+ }
159
+ None => bug ! ( "couldn't read immediate from {:?}" , place) ,
160
+ }
175
161
}
176
- None => None ,
177
162
}
178
163
}
164
+
179
165
ty:: Str => {
180
166
bug ! ( "ty::Str should have been handled in ty::Ref branch that uses raw bytes" ) ;
181
167
}
0 commit comments