@@ -174,12 +174,50 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
174174 }
175175 }
176176
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+
177210 /// Generates the code to perform a test.
178211 pub fn perform_test ( & mut self ,
179212 block : BasicBlock ,
180213 place : & Place < ' tcx > ,
181214 test : & Test < ' tcx > )
182215 -> Vec < BasicBlock > {
216+ debug ! ( "perform_test({:?}, {:?}: {:?}, {:?})" ,
217+ block,
218+ place,
219+ place. ty( & self . local_decls, self . hir. tcx( ) ) ,
220+ test) ;
183221 let source_info = self . source_info ( test. span ) ;
184222 match test. kind {
185223 TestKind :: Switch { adt_def, ref variants } => {
@@ -258,45 +296,35 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
258296 ret
259297 }
260298
261- TestKind :: Eq { value, mut ty } => {
299+ TestKind :: Eq { value, ty } => {
300+ let tcx = self . hir . tcx ( ) ;
262301 let mut val = Operand :: Copy ( place. clone ( ) ) ;
263302
264303 // If we're using b"..." as a pattern, we need to insert an
265304 // 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 {
282310 let array_ty = tcx. mk_array ( tcx. types . u8 , bytes. data . len ( ) as u64 ) ;
283311 let array_ref = tcx. mk_imm_ref ( tcx. types . re_static , array_ty) ;
284312 let array = self . literal_operand ( test. span , array_ref, Literal :: Value {
285313 value
286314 } ) ;
287315
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)
292319 } else {
293- self . literal_operand ( test. span , ty, Literal :: Value {
320+ ( self . literal_operand ( test. span , ty, Literal :: Value {
294321 value
295- } )
322+ } ) , val )
296323 } ;
297324
298325 // Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
299326 let fail = self . cfg . start_new_block ( ) ;
327+ let ty = expect. ty ( & self . local_decls , tcx) ;
300328 if let ty:: TyRef ( _, mt) = ty. sty {
301329 assert ! ( ty. is_slice( ) ) ;
302330 let eq_def_id = self . hir . tcx ( ) . lang_items ( ) . eq_trait ( ) . unwrap ( ) ;
0 commit comments