@@ -11,7 +11,6 @@ use std::sync::Arc;
1111use  rustc_data_structures:: fx:: FxIndexMap ; 
1212use  rustc_hir:: { LangItem ,  RangeEnd } ; 
1313use  rustc_middle:: mir:: * ; 
14- use  rustc_middle:: ty:: adjustment:: PointerCoercion ; 
1514use  rustc_middle:: ty:: util:: IntTypeExt ; 
1615use  rustc_middle:: ty:: { self ,  GenericArg ,  Ty ,  TyCtxt } ; 
1716use  rustc_middle:: { bug,  span_bug} ; 
@@ -178,21 +177,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
178177                    _ => { } 
179178                } 
180179
180+                 assert_eq ! ( expect_ty,  ty) ; 
181181                if  !ty. is_scalar ( )  { 
182182                    // Use `PartialEq::eq` instead of `BinOp::Eq` 
183183                    // (the binop can only handle primitives) 
184-                     self . non_scalar_compare ( 
184+                     // Make sure that we do *not* call any user-defined code here. 
185+                     // The only type that can end up here is string literals, which have their 
186+                     // comparison defined in `core`. 
187+                     // (Interestingly this means that exhaustiveness analysis relies, for soundness, 
188+                     // on the `PartialEq` impl for `str` to b correct!) 
189+                     match  * ty. kind ( )  { 
190+                         ty:: Ref ( _,  deref_ty,  _)  if  deref_ty == self . tcx . types . str_  => { } 
191+                         _ => { 
192+                             span_bug ! ( source_info. span,  "invalid type for non-scalar compare: {ty}" ) 
193+                         } 
194+                     } ; 
195+                     self . string_compare ( 
185196                        block, 
186197                        success_block, 
187198                        fail_block, 
188199                        source_info, 
189200                        expect, 
190-                         expect_ty, 
191201                        Operand :: Copy ( place) , 
192-                         ty, 
193202                    ) ; 
194203                }  else  { 
195-                     assert_eq ! ( expect_ty,  ty) ; 
196204                    self . compare ( 
197205                        block, 
198206                        success_block, 
@@ -370,97 +378,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
370378        ) ; 
371379    } 
372380
373-     /// Compare two values using `<T as std::compare::PartialEq>::eq`. 
374- /// If the values are already references, just call it directly, otherwise 
375- /// take a reference to the values first and then call it. 
376- fn  non_scalar_compare ( 
381+     /// Compare two values of type `&str` using `<str as std::cmp::PartialEq>::eq`. 
382+ fn  string_compare ( 
377383        & mut  self , 
378384        block :  BasicBlock , 
379385        success_block :  BasicBlock , 
380386        fail_block :  BasicBlock , 
381387        source_info :  SourceInfo , 
382-         mut  expect :  Operand < ' tcx > , 
383-         expect_ty :  Ty < ' tcx > , 
384-         mut  val :  Operand < ' tcx > , 
385-         mut  ty :  Ty < ' tcx > , 
388+         expect :  Operand < ' tcx > , 
389+         val :  Operand < ' tcx > , 
386390    )  { 
387-         // If we're using `b"..."` as a pattern, we need to insert an 
388-         // unsizing coercion, as the byte string has the type `&[u8; N]`. 
389-         // 
390-         // We want to do this even when the scrutinee is a reference to an 
391-         // array, so we can call `<[u8]>::eq` rather than having to find an 
392-         // `<[u8; N]>::eq`. 
393-         let  unsize = |ty :  Ty < ' tcx > | match  ty. kind ( )  { 
394-             ty:: Ref ( region,  rty,  _)  => match  rty. kind ( )  { 
395-                 ty:: Array ( inner_ty,  n)  => Some ( ( region,  inner_ty,  n) ) , 
396-                 _ => None , 
397-             } , 
398-             _ => None , 
399-         } ; 
400-         let  opt_ref_ty = unsize ( ty) ; 
401-         let  opt_ref_test_ty = unsize ( expect_ty) ; 
402-         match  ( opt_ref_ty,  opt_ref_test_ty)  { 
403-             // nothing to do, neither is an array 
404-             ( None ,  None )  => { } 
405-             ( Some ( ( region,  elem_ty,  _) ) ,  _)  | ( None ,  Some ( ( region,  elem_ty,  _) ) )  => { 
406-                 let  tcx = self . tcx ; 
407-                 // make both a slice 
408-                 ty = Ty :: new_imm_ref ( tcx,  * region,  Ty :: new_slice ( tcx,  * elem_ty) ) ; 
409-                 if  opt_ref_ty. is_some ( )  { 
410-                     let  temp = self . temp ( ty,  source_info. span ) ; 
411-                     self . cfg . push_assign ( 
412-                         block, 
413-                         source_info, 
414-                         temp, 
415-                         Rvalue :: Cast ( 
416-                             CastKind :: PointerCoercion ( 
417-                                 PointerCoercion :: Unsize , 
418-                                 CoercionSource :: Implicit , 
419-                             ) , 
420-                             val, 
421-                             ty, 
422-                         ) , 
423-                     ) ; 
424-                     val = Operand :: Copy ( temp) ; 
425-                 } 
426-                 if  opt_ref_test_ty. is_some ( )  { 
427-                     let  slice = self . temp ( ty,  source_info. span ) ; 
428-                     self . cfg . push_assign ( 
429-                         block, 
430-                         source_info, 
431-                         slice, 
432-                         Rvalue :: Cast ( 
433-                             CastKind :: PointerCoercion ( 
434-                                 PointerCoercion :: Unsize , 
435-                                 CoercionSource :: Implicit , 
436-                             ) , 
437-                             expect, 
438-                             ty, 
439-                         ) , 
440-                     ) ; 
441-                     expect = Operand :: Move ( slice) ; 
442-                 } 
443-             } 
444-         } 
445- 
446-         // Figure out the type on which we are calling `PartialEq`. This involves an extra wrapping 
447-         // reference: we can only compare two `&T`, and then compare_ty will be `T`. 
448-         // Make sure that we do *not* call any user-defined code here. 
449-         // The only types that can end up here are string and byte literals, 
450-         // which have their comparison defined in `core`. 
451-         // (Interestingly this means that exhaustiveness analysis relies, for soundness, 
452-         // on the `PartialEq` impls for `str` and `[u8]` to b correct!) 
453-         let  compare_ty = match  * ty. kind ( )  { 
454-             ty:: Ref ( _,  deref_ty,  _) 
455-                 if  deref_ty == self . tcx . types . str_  || deref_ty != self . tcx . types . u8  =>
456-             { 
457-                 deref_ty
458-             } 
459-             _ => span_bug ! ( source_info. span,  "invalid type for non-scalar compare: {}" ,  ty) , 
460-         } ; 
461- 
391+         let  str_ty = self . tcx . types . str_ ; 
462392        let  eq_def_id = self . tcx . require_lang_item ( LangItem :: PartialEq ,  Some ( source_info. span ) ) ; 
463-         let  method = trait_method ( self . tcx ,  eq_def_id,  sym:: eq,  [ compare_ty ,  compare_ty ] ) ; 
393+         let  method = trait_method ( self . tcx ,  eq_def_id,  sym:: eq,  [ str_ty ,  str_ty ] ) ; 
464394
465395        let  bool_ty = self . tcx . types . bool ; 
466396        let  eq_result = self . temp ( bool_ty,  source_info. span ) ; 
0 commit comments