@@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer};
1111use rustc_errors:: codes:: * ;
1212use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
1313use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
14- use rustc_hir:: { self as hir, RangeEnd } ;
14+ use rustc_hir:: { self as hir, LangItem , RangeEnd } ;
1515use rustc_index:: Idx ;
1616use rustc_middle:: mir:: interpret:: LitToConstInput ;
1717use rustc_middle:: thir:: {
@@ -650,7 +650,26 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
650650 // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
651651 // pattern's type means we'll properly translate it to a slice reference pattern. This works
652652 // because slices and arrays have the same valtree representation.
653- let ct_ty = pat_ty. unwrap_or_else ( || self . typeck_results . node_type ( expr. hir_id ) ) ;
653+ // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
654+ // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
655+ // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
656+ // superseded by a more general implementation of deref patterns.
657+ let ct_ty = match pat_ty {
658+ Some ( pat_ty)
659+ if let ty:: Adt ( def, _) = * pat_ty. kind ( )
660+ && self . tcx . is_lang_item ( def. did ( ) , LangItem :: String ) =>
661+ {
662+ if !self . tcx . features ( ) . string_deref_patterns ( ) {
663+ span_bug ! (
664+ expr. span,
665+ "matching on `String` went through without enabling string_deref_patterns"
666+ ) ;
667+ }
668+ self . typeck_results . node_type ( expr. hir_id )
669+ }
670+ Some ( pat_ty) => pat_ty,
671+ None => self . typeck_results . node_type ( expr. hir_id ) ,
672+ } ;
654673 let lit_input = LitToConstInput { lit : & lit. node , ty : ct_ty, neg } ;
655674 let constant = self . tcx . at ( expr. span ) . lit_to_const ( lit_input) ;
656675 self . const_to_pat ( constant, ct_ty, expr. hir_id , lit. span ) . kind
0 commit comments