about summary refs log tree commit diff
path: root/compiler/rustc_mir_build/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src')
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs23
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs14
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs10
4 files changed, 46 insertions, 3 deletions
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index 73cc3c86e22..210b9cce581 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -146,6 +146,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let mut place = place;
                 let mut block = block;
                 match ty.kind() {
+                    ty::Str => {
+                        // String literal patterns may have type `str` if `deref_patterns` is
+                        // enabled, in order to allow `deref!("..."): String`. In this case, `value`
+                        // is of type `&str`, so we compare it to `&place`.
+                        if !tcx.features().deref_patterns() {
+                            span_bug!(
+                                test.span,
+                                "matching on `str` went through without enabling deref_patterns"
+                            );
+                        }
+                        let re_erased = tcx.lifetimes.re_erased;
+                        let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
+                        let ref_place = self.temp(ref_str_ty, test.span);
+                        // `let ref_place: &str = &place;`
+                        self.cfg.push_assign(
+                            block,
+                            self.source_info(test.span),
+                            ref_place,
+                            Rvalue::Ref(re_erased, BorrowKind::Shared, place),
+                        );
+                        place = ref_place;
+                        ty = ref_str_ty;
+                    }
                     ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => {
                         if !tcx.features().string_deref_patterns() {
                             span_bug!(
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index e42336a1dbb..4e4b11b8fa6 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -1530,7 +1530,7 @@ fn build_scope_drops<'tcx>(
                 // path, then don't generate the drop. (We only take this into
                 // account for non-unwind paths so as not to disturb the
                 // caching mechanism.)
-                if scope.moved_locals.iter().any(|&o| o == local) {
+                if scope.moved_locals.contains(&local) {
                     continue;
                 }
 
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index b3210813703..b4fa55e1c1f 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -37,13 +37,23 @@ pub(crate) fn lit_to_const<'tcx>(
             let str_bytes = s.as_str().as_bytes();
             ty::ValTree::from_raw_bytes(tcx, str_bytes)
         }
+        (ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => {
+            // String literal patterns may have type `str` if `deref_patterns` is enabled, in order
+            // to allow `deref!("..."): String`.
+            let str_bytes = s.as_str().as_bytes();
+            ty::ValTree::from_raw_bytes(tcx, str_bytes)
+        }
         (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
-            if matches!(inner_ty.kind(), ty::Slice(_)) =>
+            if matches!(inner_ty.kind(), ty::Slice(_) | ty::Array(..)) =>
         {
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
-        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+        (ast::LitKind::ByteStr(data, _), ty::Slice(_) | ty::Array(..))
+            if tcx.features().deref_patterns() =>
+        {
+            // Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
+            // enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index a40001bf745..b7d203e3cd7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -280,6 +280,16 @@ impl<'tcx> ConstToPat<'tcx> {
                 slice: None,
                 suffix: Box::new([]),
             },
+            ty::Str => {
+                // String literal patterns may have type `str` if `deref_patterns` is enabled, in
+                // order to allow `deref!("..."): String`. Since we need a `&str` for the comparison
+                // when lowering to MIR in `Builder::perform_test`, treat the constant as a `&str`.
+                // This works because `str` and `&str` have the same valtree representation.
+                let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty);
+                PatKind::Constant {
+                    value: mir::Const::Ty(ref_str_ty, ty::Const::new_value(tcx, cv, ref_str_ty)),
+                }
+            }
             ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
                 // `&str` is represented as a valtree, let's keep using this
                 // optimization for now.