about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock69
-rw-r--r--Cargo.toml2
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs11
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs113
4 files changed, 93 insertions, 102 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fd9ca9b769c..068baaecc48 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -167,7 +167,7 @@ checksum = "5676cea088c32290fe65c82895be9d06dd21e0fa49bb97ca840529e9417ab71a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
  "synstructure",
 ]
 
@@ -314,17 +314,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "derivative"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
 name = "derive_arbitrary"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -332,7 +321,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -1438,47 +1427,47 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.33.0"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5313d7f243b63ef9e58d94355b11aa8499f1328055f1f58adf0a5ea7d2faca"
+checksum = "322b751895cc4a0a2ee0c6ab36ec80bc8abf5f8d76254c482f96f03c27c92ebe"
 dependencies = [
  "arrayvec",
- "ra-ap-rustc_index_macros 0.33.0",
+ "ra-ap-rustc_index_macros 0.35.0",
  "smallvec",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.35.0"
+version = "0.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322b751895cc4a0a2ee0c6ab36ec80bc8abf5f8d76254c482f96f03c27c92ebe"
+checksum = "f8a41dee58608b1fc93779ea365edaa70ac9927e3335ae914b675be0fa063cd7"
 dependencies = [
  "arrayvec",
- "ra-ap-rustc_index_macros 0.35.0",
+ "ra-ap-rustc_index_macros 0.36.0",
  "smallvec",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.33.0"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a83108ebf3e73dde205b9c25706209bcd7736480820f90ded28eabaf8b469f25"
+checksum = "054e25eac52f0506c1309ca4317c11ad4925d7b99eb897f71aa7c3cbafb46c2b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
  "synstructure",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.35.0"
+version = "0.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "054e25eac52f0506c1309ca4317c11ad4925d7b99eb897f71aa7c3cbafb46c2b"
+checksum = "fbfe98def54c4337a2f7d8233850bd5d5349972b185fe8a0db2b979164b30ed8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
  "synstructure",
 ]
 
@@ -1504,12 +1493,11 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.33.0"
+version = "0.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c4085e0c771fd4b883930b599ef42966b855762bbe4052c17673b3253421a6d"
+checksum = "b5529bffec7530b4a3425640bfdfd9b95d87c4c620f740266c0de6572561aab4"
 dependencies = [
- "derivative",
- "ra-ap-rustc_index 0.33.0",
+ "ra-ap-rustc_index 0.36.0",
  "rustc-hash",
  "rustc_apfloat",
  "smallvec",
@@ -1649,7 +1637,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -1736,7 +1724,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -1759,7 +1747,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -1838,17 +1826,6 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
 version = "2.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
@@ -1866,7 +1843,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
  "unicode-xid",
 ]
 
@@ -1955,7 +1932,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -2056,7 +2033,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index e67192cfe18..2cc3b0a0bc7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -83,7 +83,7 @@ ra-ap-rustc_lexer = { version = "0.35.0", default-features = false }
 ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false }
 ra-ap-rustc_index = { version = "0.35.0", default-features = false }
 ra-ap-rustc_abi = { version = "0.35.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.33.0", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.36.0", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 sourcegen = { path = "./crates/sourcegen" }
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index eda8f2371c9..52e635a26ea 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -153,14 +153,7 @@ impl ExprValidator {
         }
 
         let pattern_arena = Arena::new();
-        let ty_arena = Arena::new();
-        let cx = MatchCheckCtx::new(
-            self.owner.module(db.upcast()),
-            self.owner,
-            db,
-            &pattern_arena,
-            &ty_arena,
-        );
+        let cx = MatchCheckCtx::new(self.owner.module(db.upcast()), self.owner, db, &pattern_arena);
 
         let mut m_arms = Vec::with_capacity(arms.len());
         let mut has_lowering_errors = false;
@@ -207,7 +200,7 @@ impl ExprValidator {
         }
 
         let report = match compute_match_usefulness(
-            rustc_pattern_analysis::MatchCtxt { tycx: &cx },
+            &cx,
             m_arms.as_slice(),
             scrut_ty.clone(),
             ValidityConstraint::ValidOnly,
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 0b595042cd5..51be8960b8c 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -9,7 +9,7 @@ use rustc_pattern_analysis::{
     index::IdxContainer,
     Captures, TypeCx,
 };
-use smallvec::SmallVec;
+use smallvec::{smallvec, SmallVec};
 use stdx::never;
 use typed_arena::Arena;
 
@@ -41,8 +41,14 @@ pub(crate) struct MatchCheckCtx<'p> {
     body: DefWithBodyId,
     pub(crate) db: &'p dyn HirDatabase,
     pub(crate) pattern_arena: &'p Arena<DeconstructedPat<'p>>,
-    ty_arena: &'p Arena<Ty>,
     exhaustive_patterns: bool,
+    min_exhaustive_patterns: bool,
+}
+
+#[derive(Clone)]
+pub(crate) struct PatData<'p> {
+    /// Keep db around so that we can print variant names in `Debug`.
+    pub(crate) db: &'p dyn HirDatabase,
 }
 
 impl<'p> MatchCheckCtx<'p> {
@@ -51,11 +57,12 @@ impl<'p> MatchCheckCtx<'p> {
         body: DefWithBodyId,
         db: &'p dyn HirDatabase,
         pattern_arena: &'p Arena<DeconstructedPat<'p>>,
-        ty_arena: &'p Arena<Ty>,
     ) -> Self {
         let def_map = db.crate_def_map(module.krate());
         let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns");
-        Self { module, body, db, pattern_arena, exhaustive_patterns, ty_arena }
+        let min_exhaustive_patterns =
+            def_map.is_unstable_feature_enabled("min_exhaustive_patterns");
+        Self { module, body, db, pattern_arena, exhaustive_patterns, min_exhaustive_patterns }
     }
 
     fn is_uninhabited(&self, ty: &Ty) -> bool {
@@ -75,18 +82,15 @@ impl<'p> MatchCheckCtx<'p> {
         }
     }
 
-    fn variant_id_for_adt(&self, ctor: &Constructor<Self>, adt: hir_def::AdtId) -> VariantId {
+    fn variant_id_for_adt(ctor: &Constructor<Self>, adt: hir_def::AdtId) -> Option<VariantId> {
         match ctor {
-            &Variant(id) => id.into(),
-            Struct | UnionField => {
-                assert!(!matches!(adt, hir_def::AdtId::EnumId(_)));
-                match adt {
-                    hir_def::AdtId::EnumId(_) => unreachable!(),
-                    hir_def::AdtId::StructId(id) => id.into(),
-                    hir_def::AdtId::UnionId(id) => id.into(),
-                }
-            }
-            _ => panic!("bad constructor {self:?} for adt {adt:?}"),
+            &Variant(id) => Some(id.into()),
+            Struct | UnionField => match adt {
+                hir_def::AdtId::EnumId(_) => None,
+                hir_def::AdtId::StructId(id) => Some(id.into()),
+                hir_def::AdtId::UnionId(id) => Some(id.into()),
+            },
+            _ => panic!("bad constructor {ctor:?} for adt {adt:?}"),
         }
     }
 
@@ -200,7 +204,7 @@ impl<'p> MatchCheckCtx<'p> {
                                 Wildcard
                             }
                         };
-                        let variant = self.variant_id_for_adt(&ctor, adt.0);
+                        let variant = Self::variant_id_for_adt(&ctor, adt.0).unwrap();
                         let fields_len = variant.variant_data(self.db.upcast()).fields().len();
                         // For each field in the variant, we store the relevant index into `self.fields` if any.
                         let mut field_id_to_id: Vec<Option<usize>> = vec![None; fields_len];
@@ -241,7 +245,8 @@ impl<'p> MatchCheckCtx<'p> {
                 fields = self.pattern_arena.alloc_extend(subpats);
             }
         }
-        DeconstructedPat::new(ctor, fields, pat.ty.clone(), ())
+        let data = PatData { db: self.db };
+        DeconstructedPat::new(ctor, fields, pat.ty.clone(), data)
     }
 
     pub(crate) fn hoist_witness_pat(&self, pat: &WitnessPat<'p>) -> Pat {
@@ -266,7 +271,7 @@ impl<'p> MatchCheckCtx<'p> {
                     PatKind::Deref { subpattern: subpatterns.next().unwrap() }
                 }
                 TyKind::Adt(adt, substs) => {
-                    let variant = self.variant_id_for_adt(pat.ctor(), adt.0);
+                    let variant = Self::variant_id_for_adt(pat.ctor(), adt.0).unwrap();
                     let subpatterns = self
                         .list_variant_nonhidden_fields(pat.ty(), variant)
                         .zip(subpatterns)
@@ -307,11 +312,14 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
     type VariantIdx = EnumVariantId;
     type StrLit = Void;
     type ArmData = ();
-    type PatData = ();
+    type PatData = PatData<'p>;
 
     fn is_exhaustive_patterns_feature_on(&self) -> bool {
         self.exhaustive_patterns
     }
+    fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
+        self.min_exhaustive_patterns
+    }
 
     fn ctor_arity(
         &self,
@@ -327,7 +335,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
                         // patterns. If we're here we can assume this is a box pattern.
                         1
                     } else {
-                        let variant = self.variant_id_for_adt(ctor, adt);
+                        let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
                         self.list_variant_nonhidden_fields(ty, variant).count()
                     }
                 }
@@ -347,54 +355,51 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
         }
     }
 
-    fn ctor_sub_tys(
-        &self,
-        ctor: &rustc_pattern_analysis::constructor::Constructor<Self>,
-        ty: &Self::Ty,
-    ) -> &[Self::Ty] {
-        use std::iter::once;
-        fn alloc<'a>(cx: &'a MatchCheckCtx<'_>, iter: impl Iterator<Item = Ty>) -> &'a [Ty] {
-            cx.ty_arena.alloc_extend(iter)
-        }
-        match ctor {
+    fn ctor_sub_tys<'a>(
+        &'a self,
+        ctor: &'a rustc_pattern_analysis::constructor::Constructor<Self>,
+        ty: &'a Self::Ty,
+    ) -> impl Iterator<Item = Self::Ty> + ExactSizeIterator + Captures<'a> {
+        let single = |ty| smallvec![ty];
+        let tys: SmallVec<[_; 2]> = match ctor {
             Struct | Variant(_) | UnionField => match ty.kind(Interner) {
                 TyKind::Tuple(_, substs) => {
                     let tys = substs.iter(Interner).map(|ty| ty.assert_ty_ref(Interner));
-                    alloc(self, tys.cloned())
+                    tys.cloned().collect()
                 }
-                TyKind::Ref(.., rty) => alloc(self, once(rty.clone())),
+                TyKind::Ref(.., rty) => single(rty.clone()),
                 &TyKind::Adt(AdtId(adt), ref substs) => {
                     if is_box(self.db, adt) {
                         // The only legal patterns of type `Box` (outside `std`) are `_` and box
                         // patterns. If we're here we can assume this is a box pattern.
                         let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
-                        alloc(self, once(subst_ty))
+                        single(subst_ty)
                     } else {
-                        let variant = self.variant_id_for_adt(ctor, adt);
-                        let tys = self.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty);
-                        alloc(self, tys)
+                        let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
+                        self.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty).collect()
                     }
                 }
                 ty_kind => {
                     never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind);
-                    alloc(self, once(ty.clone()))
+                    single(ty.clone())
                 }
             },
             Ref => match ty.kind(Interner) {
-                TyKind::Ref(.., rty) => alloc(self, once(rty.clone())),
+                TyKind::Ref(.., rty) => single(rty.clone()),
                 ty_kind => {
                     never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind);
-                    alloc(self, once(ty.clone()))
+                    single(ty.clone())
                 }
             },
             Slice(_) => unreachable!("Found a `Slice` constructor in match checking"),
             Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
-            | NonExhaustive | Hidden | Missing | Wildcard => &[],
+            | NonExhaustive | Hidden | Missing | Wildcard => smallvec![],
             Or => {
                 never!("called `Fields::wildcards` on an `Or` ctor");
-                &[]
+                smallvec![]
             }
-        }
+        };
+        tys.into_iter()
     }
 
     fn ctors_for_ty(
@@ -456,11 +461,27 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
         })
     }
 
-    fn debug_pat(
-        _f: &mut fmt::Formatter<'_>,
-        _pat: &rustc_pattern_analysis::pat::DeconstructedPat<'_, Self>,
+    fn write_variant_name(
+        f: &mut fmt::Formatter<'_>,
+        pat: &rustc_pattern_analysis::pat::DeconstructedPat<'_, Self>,
     ) -> fmt::Result {
-        // FIXME: implement this, as using `unimplemented!()` causes panics in `tracing`.
+        let variant =
+            pat.ty().as_adt().and_then(|(adt, _)| Self::variant_id_for_adt(pat.ctor(), adt));
+
+        let db = pat.data().unwrap().db;
+        if let Some(variant) = variant {
+            match variant {
+                VariantId::EnumVariantId(v) => {
+                    write!(f, "{}", db.enum_variant_data(v).name.display(db.upcast()))?;
+                }
+                VariantId::StructId(s) => {
+                    write!(f, "{}", db.struct_data(s).name.display(db.upcast()))?
+                }
+                VariantId::UnionId(u) => {
+                    write!(f, "{}", db.union_data(u).name.display(db.upcast()))?
+                }
+            }
+        }
         Ok(())
     }