@@ -174,33 +174,78 @@ impl<'a,'tcx> Builder<'a,'tcx> {
174
174
targets
175
175
}
176
176
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
+ }
198
194
}
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
+ } )
199
212
} ;
200
- let val = Operand :: Consume ( lvalue. clone ( ) ) ;
213
+
214
+ // Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
201
215
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
+ }
204
249
}
205
250
206
251
TestKind :: Range { ref lo, ref hi, ty } => {
0 commit comments