about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-07 16:22:26 +0000
committerbors <bors@rust-lang.org>2024-03-07 16:22:26 +0000
commitbbb441ec6d827e56fa5ea441dd0cef209a535bd8 (patch)
tree49be091b7b5a81e65b9d85ce41446247f491ce16
parentb1f6d56e44c1ce67b5e723776e948c5c82f794d4 (diff)
parente31484c108c91aff78510a5dc344dcd2f194a29c (diff)
downloadrust-bbb441ec6d827e56fa5ea441dd0cef209a535bd8.tar.gz
rust-bbb441ec6d827e56fa5ea441dd0cef209a535bd8.zip
Auto merge of #16778 - Nadrieril:update-pat-ana, r=lnicola
Update `rustc_pattern_analysis` to 0.42.0

There was an important API change in 0.41.0, and (hopefully) a fix for https://github.com/rust-lang/rust-analyzer/issues/16774 in 0.42.0.
-rw-r--r--Cargo.lock24
-rw-r--r--Cargo.toml10
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs2
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs106
-rw-r--r--crates/hir-ty/src/layout.rs6
5 files changed, 75 insertions, 73 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 03f9ffb1ec9..903141eee9a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1425,9 +1425,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.40.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2548746ce549476a7aa982099dfe5139f939099d83077b3393baf5e920292f64"
+checksum = "c2ae52e2d5b08762c9464b541345f519b8719d57b643b73632bade43ecece9dc"
 dependencies = [
  "bitflags 2.4.2",
  "ra-ap-rustc_index",
@@ -1436,9 +1436,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.40.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "371db64f1be25aae96650b5528c76066ac325f0fe23efec0aab1179d75eea5c3"
+checksum = "bfd7e10c7853fe79443d46e1d2d8ab09fe99926118e59653fb8b480d5045f126"
 dependencies = [
  "arrayvec",
  "ra-ap-rustc_index_macros",
@@ -1447,9 +1447,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.40.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4a454193807f557a991f52157250fd2db95abfb96da65e85355e6949802a98"
+checksum = "47f1d1c589be6c9a9e852fadee0e60329c0f862e87442ac2fe5adae30663cc76"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1459,9 +1459,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.40.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f346eb8d73041fd48280373f929803c4650771da631b1d076d5ed0ca4216b48"
+checksum = "fa852373a757b4c723bbdc96ced7f575cad68a1e266e45fee12bc4c69a482d80"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1469,9 +1469,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.40.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85f8a94cf47d86b93e7c2440de4308de74e1d5cb71ed3a9df7dcde2550742e6e"
+checksum = "2afe3c49accd95a53ac4d72ae13bafc7d115bdd80c8cd56ab09e6fc68f482210"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1479,9 +1479,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.40.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9cb49490fadb58e6b8cc825f73157a33730495bfd5c6e9eef067a4b50ad1836"
+checksum = "1253da23515d80c377a3998731e0ec3794997b62b989fd47db73efbde6a0bd7c"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash",
diff --git a/Cargo.toml b/Cargo.toml
index eb3be72396c..440f46a938b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.40.0", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.40.0", default-features = false }
-ra-ap-rustc_index = { version = "0.40.0", default-features = false }
-ra-ap-rustc_abi = { version = "0.40.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.40.0", default-features = false }
+ra-ap-rustc_lexer = { version = "0.42.0", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.42.0", default-features = false }
+ra-ap-rustc_index = { version = "0.42.0", default-features = false }
+ra-ap-rustc_abi = { version = "0.42.0", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.42.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 dfc0a25bf46..69205f8fddf 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -239,6 +239,7 @@ impl ExprValidator {
             m_arms.as_slice(),
             scrut_ty.clone(),
             ValidityConstraint::ValidOnly,
+            None,
         ) {
             Ok(report) => report,
             Err(()) => return,
@@ -283,6 +284,7 @@ impl ExprValidator {
                 &[match_arm],
                 ty.clone(),
                 ValidityConstraint::ValidOnly,
+                None,
             ) {
                 Ok(v) => v,
                 Err(e) => {
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 e98a946a870..ca058428796 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
 use rustc_pattern_analysis::{
     constructor::{Constructor, ConstructorSet, VariantVisibility},
     index::IdxContainer,
-    Captures, TypeCx,
+    Captures, PrivateUninhabitedField, TypeCx,
 };
 use smallvec::{smallvec, SmallVec};
 use stdx::never;
@@ -88,39 +88,21 @@ impl<'p> MatchCheckCtx<'p> {
         }
     }
 
-    // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
-    // uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
-    // This lists the fields we keep along with their types.
-    fn list_variant_nonhidden_fields<'a>(
+    // This lists the fields of a variant along with their types.
+    fn list_variant_fields<'a>(
         &'a self,
         ty: &'a Ty,
         variant: VariantId,
     ) -> impl Iterator<Item = (LocalFieldId, Ty)> + Captures<'a> + Captures<'p> {
-        let cx = self;
-        let (adt, substs) = ty.as_adt().unwrap();
-
-        let adt_is_local = variant.module(cx.db.upcast()).krate() == cx.module.krate();
-
-        // Whether we must not match the fields of this variant exhaustively.
-        let is_non_exhaustive =
-            cx.db.attrs(variant.into()).by_key("non_exhaustive").exists() && !adt_is_local;
+        let (_, substs) = ty.as_adt().unwrap();
 
-        let visibility = cx.db.field_visibilities(variant);
-        let field_ty = cx.db.field_types(variant);
-        let fields_len = variant.variant_data(cx.db.upcast()).fields().len() as u32;
+        let field_tys = self.db.field_types(variant);
+        let fields_len = variant.variant_data(self.db.upcast()).fields().len() as u32;
 
-        (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).filter_map(move |fid| {
-            let ty = field_ty[fid].clone().substitute(Interner, substs);
-            let ty = normalize(cx.db, cx.db.trait_environment_for_body(cx.body), ty);
-            let is_visible = matches!(adt, hir_def::AdtId::EnumId(..))
-                || visibility[fid].is_visible_from(cx.db.upcast(), cx.module);
-            let is_uninhabited = cx.is_uninhabited(&ty);
-
-            if is_uninhabited && (!is_visible || is_non_exhaustive) {
-                None
-            } else {
-                Some((fid, ty))
-            }
+        (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
+            let ty = field_tys[fid].clone().substitute(Interner, substs);
+            let ty = normalize(self.db, self.db.trait_environment_for_body(self.body), ty);
+            (fid, ty)
         })
     }
 
@@ -199,23 +181,16 @@ impl<'p> MatchCheckCtx<'p> {
                             }
                         };
                         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];
-                        let tys = self
-                            .list_variant_nonhidden_fields(&pat.ty, variant)
-                            .enumerate()
-                            .map(|(i, (fid, ty))| {
-                                let field_idx: u32 = fid.into_raw().into();
-                                field_id_to_id[field_idx as usize] = Some(i);
-                                ty
-                            });
-                        let mut wilds: Vec<_> = tys.map(DeconstructedPat::wildcard).collect();
+                        // Fill a vec with wildcards, then place the fields we have at the right
+                        // index.
+                        let mut wilds: Vec<_> = self
+                            .list_variant_fields(&pat.ty, variant)
+                            .map(|(_, ty)| ty)
+                            .map(DeconstructedPat::wildcard)
+                            .collect();
                         for pat in subpatterns {
-                            let field_idx: u32 = pat.field.into_raw().into();
-                            if let Some(i) = field_id_to_id[field_idx as usize] {
-                                wilds[i] = self.lower_pat(&pat.pattern);
-                            }
+                            let field_id: u32 = pat.field.into_raw().into();
+                            wilds[field_id as usize] = self.lower_pat(&pat.pattern);
                         }
                         fields = wilds;
                     }
@@ -263,7 +238,7 @@ impl<'p> MatchCheckCtx<'p> {
                 TyKind::Adt(adt, substs) => {
                     let variant = Self::variant_id_for_adt(pat.ctor(), adt.0).unwrap();
                     let subpatterns = self
-                        .list_variant_nonhidden_fields(pat.ty(), variant)
+                        .list_variant_fields(pat.ty(), variant)
                         .zip(subpatterns)
                         .map(|((field, _ty), pattern)| FieldPat { field, pattern })
                         .collect();
@@ -286,7 +261,7 @@ impl<'p> MatchCheckCtx<'p> {
             Ref => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
             Slice(_) => unimplemented!(),
             &Str(void) => match void {},
-            Wildcard | NonExhaustive | Hidden => PatKind::Wild,
+            Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
             Missing | F32Range(..) | F64Range(..) | Opaque(..) | Or => {
                 never!("can't convert to pattern: {:?}", pat.ctor());
                 PatKind::Wild
@@ -326,7 +301,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
                         1
                     } else {
                         let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
-                        self.list_variant_nonhidden_fields(ty, variant).count()
+                        variant.variant_data(self.db.upcast()).fields().len()
                     }
                 }
                 _ => {
@@ -337,7 +312,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
             Ref => 1,
             Slice(..) => unimplemented!(),
             Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
-            | NonExhaustive | Hidden | Missing | Wildcard => 0,
+            | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0,
             Or => {
                 never!("The `Or` constructor doesn't have a fixed arity");
                 0
@@ -349,13 +324,13 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
         &'a self,
         ctor: &'a rustc_pattern_analysis::constructor::Constructor<Self>,
         ty: &'a Self::Ty,
-    ) -> impl ExactSizeIterator<Item = Self::Ty> + Captures<'a> {
-        let single = |ty| smallvec![ty];
+    ) -> impl ExactSizeIterator<Item = (Self::Ty, PrivateUninhabitedField)> + Captures<'a> {
+        let single = |ty| smallvec![(ty, PrivateUninhabitedField(false))];
         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));
-                    tys.cloned().collect()
+                    tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
                 }
                 TyKind::Ref(.., rty) => single(rty.clone()),
                 &TyKind::Adt(AdtId(adt), ref substs) => {
@@ -366,7 +341,27 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
                         single(subst_ty)
                     } else {
                         let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
-                        self.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty).collect()
+                        let (adt, _) = ty.as_adt().unwrap();
+
+                        let adt_is_local =
+                            variant.module(self.db.upcast()).krate() == self.module.krate();
+                        // Whether we must not match the fields of this variant exhaustively.
+                        let is_non_exhaustive =
+                            self.db.attrs(variant.into()).by_key("non_exhaustive").exists()
+                                && !adt_is_local;
+                        let visibilities = self.db.field_visibilities(variant);
+
+                        self.list_variant_fields(ty, variant)
+                            .map(move |(fid, ty)| {
+                                let is_visible = matches!(adt, hir_def::AdtId::EnumId(..))
+                                    || visibilities[fid]
+                                        .is_visible_from(self.db.upcast(), self.module);
+                                let is_uninhabited = self.is_uninhabited(&ty);
+                                let private_uninhabited =
+                                    is_uninhabited && (!is_visible || is_non_exhaustive);
+                                (ty, PrivateUninhabitedField(private_uninhabited))
+                            })
+                            .collect()
                     }
                 }
                 ty_kind => {
@@ -383,7 +378,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
             },
             Slice(_) => unreachable!("Found a `Slice` constructor in match checking"),
             Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
-            | NonExhaustive | Hidden | Missing | Wildcard => smallvec![],
+            | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => smallvec![],
             Or => {
                 never!("called `Fields::wildcards` on an `Or` ctor");
                 smallvec![]
@@ -478,6 +473,11 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
     fn bug(&self, fmt: fmt::Arguments<'_>) {
         debug!("{}", fmt)
     }
+
+    fn complexity_exceeded(&self) -> Result<(), Self::Error> {
+        // FIXME(Nadrieril): make use of the complexity counter.
+        Err(())
+    }
 }
 
 impl<'p> fmt::Debug for MatchCheckCtx<'p> {
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index be1c8d9094b..dea292711d8 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -1,6 +1,6 @@
 //! Compute the binary representation of a type
 
-use std::fmt;
+use std::{borrow::Cow, fmt};
 
 use base_db::salsa::Cycle;
 use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
@@ -114,8 +114,8 @@ struct LayoutCx<'a> {
 impl<'a> LayoutCalculator for LayoutCx<'a> {
     type TargetDataLayoutRef = &'a TargetDataLayout;
 
-    fn delayed_bug(&self, txt: String) {
-        never!("{}", txt);
+    fn delayed_bug(&self, txt: impl Into<Cow<'static, str>>) {
+        never!("{}", txt.into());
     }
 
     fn current_data_layout(&self) -> &'a TargetDataLayout {