@@ -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. 
178211pub  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