@@ -144,7 +144,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
144144 && tcx. is_lang_item ( def. did ( ) , LangItem :: String )
145145 {
146146 if !tcx. features ( ) . string_deref_patterns {
147- bug ! (
147+ span_bug ! (
148+ test. span,
148149 "matching on `String` went through without enabling string_deref_patterns"
149150 ) ;
150151 }
@@ -432,40 +433,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
432433 }
433434 }
434435
435- match * ty. kind ( ) {
436- ty:: Ref ( _, deref_ty, _) => ty = deref_ty,
437- _ => {
438- // non_scalar_compare called on non-reference type
439- let temp = self . temp ( ty, source_info. span ) ;
440- self . cfg . push_assign ( block, source_info, temp, Rvalue :: Use ( expect) ) ;
441- let ref_ty = Ty :: new_imm_ref ( self . tcx , self . tcx . lifetimes . re_erased , ty) ;
442- let ref_temp = self . temp ( ref_ty, source_info. span ) ;
443-
444- self . cfg . push_assign (
445- block,
446- source_info,
447- ref_temp,
448- Rvalue :: Ref ( self . tcx . lifetimes . re_erased , BorrowKind :: Shared , temp) ,
449- ) ;
450- expect = Operand :: Move ( ref_temp) ;
451-
452- let ref_temp = self . temp ( ref_ty, source_info. span ) ;
453- self . cfg . push_assign (
454- block,
455- source_info,
456- ref_temp,
457- Rvalue :: Ref ( self . tcx . lifetimes . re_erased , BorrowKind :: Shared , val) ,
458- ) ;
459- val = ref_temp;
436+ // Figure out the type on which we are calling `PartialEq`. This involves an extra wrapping
437+ // reference: we can only compare two `&T`, and then compare_ty will be `T`.
438+ // Make sure that we do *not* call any user-defined code here.
439+ // The only types that can end up here are string and byte literals,
440+ // which have their comparison defined in `core`.
441+ // (Interestingly this means that exhaustiveness analysis relies, for soundness,
442+ // on the `PartialEq` impls for `str` and `[u8]` to b correct!)
443+ let compare_ty = match * ty. kind ( ) {
444+ ty:: Ref ( _, deref_ty, _)
445+ if deref_ty == self . tcx . types . str_ || deref_ty != self . tcx . types . u8 =>
446+ {
447+ deref_ty
460448 }
461- }
449+ _ => span_bug ! ( source_info. span, "invalid type for non-scalar compare: {}" , ty) ,
450+ } ;
462451
463452 let eq_def_id = self . tcx . require_lang_item ( LangItem :: PartialEq , Some ( source_info. span ) ) ;
464453 let method = trait_method (
465454 self . tcx ,
466455 eq_def_id,
467456 sym:: eq,
468- self . tcx . with_opt_host_effect_param ( self . def_id , eq_def_id, [ ty , ty ] ) ,
457+ self . tcx . with_opt_host_effect_param ( self . def_id , eq_def_id, [ compare_ty , compare_ty ] ) ,
469458 ) ;
470459
471460 let bool_ty = self . tcx . types . bool ;
0 commit comments