From 1b0b4220fdaef5aa44151de36e6c719429090da3 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 7 Mar 2024 16:33:31 +0100 Subject: [PATCH] Update `rustc_pattern_analysis` to 0.42.0 --- Cargo.lock | 37 ++++-- Cargo.toml | 2 +- crates/hir-ty/src/diagnostics/expr.rs | 2 + .../diagnostics/match_check/pat_analysis.rs | 106 +++++++++--------- 4 files changed, 86 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03f9ffb1ec9..7dc899c4184 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -588,7 +588,7 @@ dependencies = [ "oorandom", "project-model", "ra-ap-rustc_abi", - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.40.0", "ra-ap-rustc_pattern_analysis", "rustc-hash", "scoped-tls", @@ -1430,7 +1430,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2548746ce549476a7aa982099dfe5139f939099d83077b3393baf5e920292f64" dependencies = [ "bitflags 2.4.2", - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.40.0", "tracing", ] @@ -1441,7 +1441,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "371db64f1be25aae96650b5528c76066ac325f0fe23efec0aab1179d75eea5c3" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros", + "ra-ap-rustc_index_macros 0.40.0", + "smallvec", +] + +[[package]] +name = "ra-ap-rustc_index" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd7e10c7853fe79443d46e1d2d8ab09fe99926118e59653fb8b480d5045f126" +dependencies = [ + "arrayvec", + "ra-ap-rustc_index_macros 0.42.0", "smallvec", ] @@ -1457,6 +1468,18 @@ dependencies = [ "synstructure", ] +[[package]] +name = "ra-ap-rustc_index_macros" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47f1d1c589be6c9a9e852fadee0e60329c0f862e87442ac2fe5adae30663cc76" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "ra-ap-rustc_lexer" version = "0.40.0" @@ -1473,17 +1496,17 @@ version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85f8a94cf47d86b93e7c2440de4308de74e1d5cb71ed3a9df7dcde2550742e6e" dependencies = [ - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.40.0", "ra-ap-rustc_lexer", ] [[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", + "ra-ap-rustc_index 0.42.0", "rustc-hash", "rustc_apfloat", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index eb3be72396c..db7d234c067 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,7 +88,7 @@ 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_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 + Captures<'a> + Captures<'p> { - let cx = self; - let (adt, substs) = ty.as_adt().unwrap(); + let (_, substs) = ty.as_adt().unwrap(); - let adt_is_local = variant.module(cx.db.upcast()).krate() == cx.module.krate(); + let field_tys = self.db.field_types(variant); + let fields_len = variant.variant_data(self.db.upcast()).fields().len() as u32; - // 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 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; - - (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> = 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, ty: &'a Self::Ty, - ) -> impl ExactSizeIterator + Captures<'a> { - let single = |ty| smallvec![ty]; + ) -> impl ExactSizeIterator + 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> {