@@ -174,33 +174,78 @@ impl<'a,'tcx> Builder<'a,'tcx> {
174174 targets
175175 }
176176
177- TestKind :: Eq { ref value, ty } => {
178- // If we're matching against &[u8] with b"...", we need to insert
179- // an unsizing coercion, as the byte string has type &[u8; N].
180- let expect = match * value {
181- ConstVal :: ByteStr ( ref bytes) if ty. is_slice ( ) => {
182- let tcx = self . hir . tcx ( ) ;
183- let array_ty = tcx. mk_array ( tcx. types . u8 , bytes. len ( ) ) ;
184- let ref_ty = tcx. mk_imm_ref ( tcx. mk_region ( ty:: ReStatic ) , array_ty) ;
185- let array = self . literal_operand ( test. span , ref_ty, Literal :: Value {
186- value : value. clone ( )
187- } ) ;
188-
189- let sliced = self . temp ( ty) ;
190- self . cfg . push_assign ( block, test. span , & sliced,
191- Rvalue :: Cast ( CastKind :: Unsize , array, ty) ) ;
192- Operand :: Consume ( sliced)
193- }
194- _ => {
195- self . literal_operand ( test. span , ty, Literal :: Value {
196- value : value. clone ( )
197- } )
177+ TestKind :: Eq { ref value, mut ty } => {
178+ let mut val = Operand :: Consume ( lvalue. clone ( ) ) ;
179+
180+ // If we're using b"..." as a pattern, we need to insert an
181+ // unsizing coercion, as the byte string has the type &[u8; N].
182+ let expect = if let ConstVal :: ByteStr ( ref bytes) = * value {
183+ let tcx = self . hir . tcx ( ) ;
184+
185+ // Unsize the lvalue to &[u8], too, if necessary.
186+ if let ty:: TyRef ( region, mt) = ty. sty {
187+ if let ty:: TyArray ( _, _) = mt. ty . sty {
188+ ty = tcx. mk_imm_ref ( region, tcx. mk_slice ( tcx. types . u8 ) ) ;
189+ let val_slice = self . temp ( ty) ;
190+ self . cfg . push_assign ( block, test. span , & val_slice,
191+ Rvalue :: Cast ( CastKind :: Unsize , val, ty) ) ;
192+ val = Operand :: Consume ( val_slice) ;
193+ }
198194 }
195+
196+ assert ! ( ty. is_slice( ) ) ;
197+
198+ let array_ty = tcx. mk_array ( tcx. types . u8 , bytes. len ( ) ) ;
199+ let array_ref = tcx. mk_imm_ref ( tcx. mk_region ( ty:: ReStatic ) , array_ty) ;
200+ let array = self . literal_operand ( test. span , array_ref, Literal :: Value {
201+ value : value. clone ( )
202+ } ) ;
203+
204+ let slice = self . temp ( ty) ;
205+ self . cfg . push_assign ( block, test. span , & slice,
206+ Rvalue :: Cast ( CastKind :: Unsize , array, ty) ) ;
207+ Operand :: Consume ( slice)
208+ } else {
209+ self . literal_operand ( test. span , ty, Literal :: Value {
210+ value : value. clone ( )
211+ } )
199212 } ;
200- let val = Operand :: Consume ( lvalue. clone ( ) ) ;
213+
214+ // Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
201215 let fail = self . cfg . start_new_block ( ) ;
202- let block = self . compare ( block, fail, test. span , BinOp :: Eq , expect, val. clone ( ) ) ;
203- vec ! [ block, fail]
216+ if let ty:: TyRef ( _, mt) = ty. sty {
217+ assert ! ( ty. is_slice( ) ) ;
218+ let eq_def_id = self . hir . tcx ( ) . lang_items . eq_trait ( ) . unwrap ( ) ;
219+ let ty = mt. ty ;
220+ let ( mty, method) = self . hir . trait_method ( eq_def_id, "eq" , ty, vec ! [ ty] ) ;
221+
222+ let bool_ty = self . hir . bool_ty ( ) ;
223+ let eq_result = self . temp ( bool_ty) ;
224+ let eq_block = self . cfg . start_new_block ( ) ;
225+ let cleanup = self . diverge_cleanup ( ) ;
226+ self . cfg . terminate ( block, Terminator :: Call {
227+ func : Operand :: Constant ( Constant {
228+ span : test. span ,
229+ ty : mty,
230+ literal : method
231+ } ) ,
232+ args : vec ! [ val, expect] ,
233+ destination : Some ( ( eq_result. clone ( ) , eq_block) ) ,
234+ cleanup : cleanup,
235+ } ) ;
236+
237+ // check the result
238+ let block = self . cfg . start_new_block ( ) ;
239+ self . cfg . terminate ( eq_block, Terminator :: If {
240+ cond : Operand :: Consume ( eq_result) ,
241+ targets : ( block, fail) ,
242+ } ) ;
243+
244+ vec ! [ block, fail]
245+ } else {
246+ let block = self . compare ( block, fail, test. span , BinOp :: Eq , expect, val) ;
247+ vec ! [ block, fail]
248+ }
204249 }
205250
206251 TestKind :: Range { ref lo, ref hi, ty } => {
0 commit comments