@@ -141,66 +141,71 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
141141 self . cfg . terminate ( block, self . source_info ( match_start_span) , terminator) ;
142142 }
143143
144- TestKind :: Eq { value, ty } => {
144+ TestKind :: Eq { value, mut ty } => {
145145 let tcx = self . tcx ;
146146 let success_block = target_block ( TestBranch :: Success ) ;
147147 let fail_block = target_block ( TestBranch :: Failure ) ;
148- if let ty:: Adt ( def, _) = ty. kind ( )
149- && tcx. is_lang_item ( def. did ( ) , LangItem :: String )
150- {
151- if !tcx. features ( ) . string_deref_patterns ( ) {
152- span_bug ! (
148+
149+ let expect_ty = value. ty ( ) ;
150+ let expect = self . literal_operand ( test. span , value) ;
151+
152+ let mut place = place;
153+ let mut block = block;
154+ match ty. kind ( ) {
155+ ty:: Adt ( def, _) if tcx. is_lang_item ( def. did ( ) , LangItem :: String ) => {
156+ if !tcx. features ( ) . string_deref_patterns ( ) {
157+ span_bug ! (
158+ test. span,
159+ "matching on `String` went through without enabling string_deref_patterns"
160+ ) ;
161+ }
162+ let re_erased = tcx. lifetimes . re_erased ;
163+ let ref_str_ty = Ty :: new_imm_ref ( tcx, re_erased, tcx. types . str_ ) ;
164+ let ref_str = self . temp ( ref_str_ty, test. span ) ;
165+ let eq_block = self . cfg . start_new_block ( ) ;
166+ // `let ref_str: &str = <String as Deref>::deref(&place);`
167+ self . call_deref (
168+ block,
169+ eq_block,
170+ place,
171+ Mutability :: Not ,
172+ ty,
173+ ref_str,
153174 test. span ,
154- "matching on `String` went through without enabling string_deref_patterns"
155175 ) ;
176+ // Since we generated a `ref_str = <String as Deref>::deref(&place) -> eq_block` terminator,
177+ // we need to add all further statements to `eq_block`.
178+ // Similarly, the normal test code should be generated for the `&str`, instead of the `String`.
179+ block = eq_block;
180+ place = ref_str;
181+ ty = ref_str_ty;
156182 }
157- let re_erased = tcx. lifetimes . re_erased ;
158- let ref_str_ty = Ty :: new_imm_ref ( tcx, re_erased, tcx. types . str_ ) ;
159- let ref_str = self . temp ( ref_str_ty, test. span ) ;
160- let eq_block = self . cfg . start_new_block ( ) ;
161- // `let ref_str: &str = <String as Deref>::deref(&place);`
162- self . call_deref (
163- block,
164- eq_block,
165- place,
166- Mutability :: Not ,
167- ty,
168- ref_str,
169- test. span ,
170- ) ;
171- self . non_scalar_compare (
172- eq_block,
173- success_block,
174- fail_block,
175- source_info,
176- value,
177- ref_str,
178- ref_str_ty,
179- ) ;
180- } else if !ty. is_scalar ( ) {
183+ _ => { }
184+ }
185+
186+ if !ty. is_scalar ( ) {
181187 // Use `PartialEq::eq` instead of `BinOp::Eq`
182188 // (the binop can only handle primitives)
183189 self . non_scalar_compare (
184190 block,
185191 success_block,
186192 fail_block,
187193 source_info,
188- value,
189- place,
194+ expect,
195+ expect_ty,
196+ Operand :: Copy ( place) ,
190197 ty,
191198 ) ;
192199 } else {
193- assert_eq ! ( value. ty( ) , ty) ;
194- let expect = self . literal_operand ( test. span , value) ;
195- let val = Operand :: Copy ( place) ;
200+ assert_eq ! ( expect_ty, ty) ;
196201 self . compare (
197202 block,
198203 success_block,
199204 fail_block,
200205 source_info,
201206 BinOp :: Eq ,
202207 expect,
203- val ,
208+ Operand :: Copy ( place ) ,
204209 ) ;
205210 }
206211 }
@@ -371,12 +376,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
371376 success_block : BasicBlock ,
372377 fail_block : BasicBlock ,
373378 source_info : SourceInfo ,
374- value : Const < ' tcx > ,
375- mut val : Place < ' tcx > ,
379+ mut expect : Operand < ' tcx > ,
380+ expect_ty : Ty < ' tcx > ,
381+ mut val : Operand < ' tcx > ,
376382 mut ty : Ty < ' tcx > ,
377383 ) {
378- let mut expect = self . literal_operand ( source_info. span , value) ;
379-
380384 // If we're using `b"..."` as a pattern, we need to insert an
381385 // unsizing coercion, as the byte string has the type `&[u8; N]`.
382386 //
@@ -391,7 +395,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
391395 _ => None ,
392396 } ;
393397 let opt_ref_ty = unsize ( ty) ;
394- let opt_ref_test_ty = unsize ( value . ty ( ) ) ;
398+ let opt_ref_test_ty = unsize ( expect_ty ) ;
395399 match ( opt_ref_ty, opt_ref_test_ty) {
396400 // nothing to do, neither is an array
397401 ( None , None ) => { }
@@ -410,11 +414,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
410414 PointerCoercion :: Unsize ,
411415 CoercionSource :: Implicit ,
412416 ) ,
413- Operand :: Copy ( val) ,
417+ val,
414418 ty,
415419 ) ,
416420 ) ;
417- val = temp;
421+ val = Operand :: Copy ( temp) ;
418422 }
419423 if opt_ref_test_ty. is_some ( ) {
420424 let slice = self . temp ( ty, source_info. span ) ;
@@ -470,11 +474,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
470474
471475 const_ : method,
472476 } ) ) ,
473- args : [ Spanned { node : Operand :: Copy ( val) , span : DUMMY_SP } , Spanned {
474- node : expect,
475- span : DUMMY_SP ,
476- } ]
477- . into ( ) ,
477+ args : [ Spanned { node : val, span : DUMMY_SP } , Spanned { node : expect, span : DUMMY_SP } ]
478+ . into ( ) ,
478479 destination : eq_result,
479480 target : Some ( eq_block) ,
480481 unwind : UnwindAction :: Continue ,
0 commit comments