@@ -174,12 +174,50 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
174
174
}
175
175
}
176
176
177
+ /// Convert a byte array or byte slice to a byte slice.
178
+ fn to_slice_operand ( & mut self ,
179
+ block : BasicBlock ,
180
+ source_info : SourceInfo ,
181
+ operand : Operand < ' tcx > )
182
+ -> Operand < ' tcx >
183
+ {
184
+ let tcx = self . hir . tcx ( ) ;
185
+ let ty = operand. ty ( & self . local_decls , tcx) ;
186
+ debug ! ( "to_slice_operand({:?}, {:?}: {:?})" , block, operand, ty) ;
187
+ match ty. sty {
188
+ ty:: TyRef ( region, mt) => match mt. ty . sty {
189
+ ty:: TyArray ( ety, _) => {
190
+ let ty = tcx. mk_imm_ref ( region, tcx. mk_slice ( ety) ) ;
191
+ let temp = self . temp ( ty, source_info. span ) ;
192
+ self . cfg . push_assign ( block, source_info, & temp,
193
+ Rvalue :: Cast ( CastKind :: Unsize , operand, ty) ) ;
194
+ Operand :: Move ( temp)
195
+ }
196
+ ty:: TySlice ( _) => operand,
197
+ _ => {
198
+ span_bug ! ( source_info. span,
199
+ "bad operand {:?}: {:?} to `to_slice_operand`" , operand, ty)
200
+ }
201
+ }
202
+ _ => {
203
+ span_bug ! ( source_info. span,
204
+ "bad operand {:?}: {:?} to `to_slice_operand`" , operand, ty)
205
+ }
206
+ }
207
+
208
+ }
209
+
177
210
/// Generates the code to perform a test.
178
211
pub fn perform_test ( & mut self ,
179
212
block : BasicBlock ,
180
213
place : & Place < ' tcx > ,
181
214
test : & Test < ' tcx > )
182
215
-> Vec < BasicBlock > {
216
+ debug ! ( "perform_test({:?}, {:?}: {:?}, {:?})" ,
217
+ block,
218
+ place,
219
+ place. ty( & self . local_decls, self . hir. tcx( ) ) ,
220
+ test) ;
183
221
let source_info = self . source_info ( test. span ) ;
184
222
match test. kind {
185
223
TestKind :: Switch { adt_def, ref variants } => {
@@ -258,45 +296,35 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
258
296
ret
259
297
}
260
298
261
- TestKind :: Eq { value, mut ty } => {
299
+ TestKind :: Eq { value, ty } => {
300
+ let tcx = self . hir . tcx ( ) ;
262
301
let mut val = Operand :: Copy ( place. clone ( ) ) ;
263
302
264
303
// If we're using b"..." as a pattern, we need to insert an
265
304
// unsizing coercion, as the byte string has the type &[u8; N].
266
- let expect = if let ConstVal :: ByteStr ( bytes) = value. val {
267
- let tcx = self . hir . tcx ( ) ;
268
-
269
- // Unsize the place to &[u8], too, if necessary.
270
- if let ty:: TyRef ( region, mt) = ty. sty {
271
- if let ty:: TyArray ( _, _) = mt. ty . sty {
272
- ty = tcx. mk_imm_ref ( region, tcx. mk_slice ( tcx. types . u8 ) ) ;
273
- let val_slice = self . temp ( ty, test. span ) ;
274
- self . cfg . push_assign ( block, source_info, & val_slice,
275
- Rvalue :: Cast ( CastKind :: Unsize , val, ty) ) ;
276
- val = Operand :: Move ( val_slice) ;
277
- }
278
- }
279
-
280
- assert ! ( ty. is_slice( ) ) ;
281
-
305
+ //
306
+ // We want to do this even when the scrutinee is a reference to an
307
+ // array, so we can call `<[u8]>::eq` rather than having to find an
308
+ // `<[u8; N]>::eq`.
309
+ let ( expect, val) = if let ConstVal :: ByteStr ( bytes) = value. val {
282
310
let array_ty = tcx. mk_array ( tcx. types . u8 , bytes. data . len ( ) as u64 ) ;
283
311
let array_ref = tcx. mk_imm_ref ( tcx. types . re_static , array_ty) ;
284
312
let array = self . literal_operand ( test. span , array_ref, Literal :: Value {
285
313
value
286
314
} ) ;
287
315
288
- let slice = self . temp ( ty, test. span ) ;
289
- self . cfg . push_assign ( block, source_info, & slice,
290
- Rvalue :: Cast ( CastKind :: Unsize , array, ty) ) ;
291
- Operand :: Move ( slice)
316
+ let val = self . to_slice_operand ( block, source_info, val) ;
317
+ let slice = self . to_slice_operand ( block, source_info, array) ;
318
+ ( slice, val)
292
319
} else {
293
- self . literal_operand ( test. span , ty, Literal :: Value {
320
+ ( self . literal_operand ( test. span , ty, Literal :: Value {
294
321
value
295
- } )
322
+ } ) , val )
296
323
} ;
297
324
298
325
// Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
299
326
let fail = self . cfg . start_new_block ( ) ;
327
+ let ty = expect. ty ( & self . local_decls , tcx) ;
300
328
if let ty:: TyRef ( _, mt) = ty. sty {
301
329
assert ! ( ty. is_slice( ) ) ;
302
330
let eq_def_id = self . hir . tcx ( ) . lang_items ( ) . eq_trait ( ) . unwrap ( ) ;
0 commit comments