diff --git a/Cargo.lock b/Cargo.lock index dc2bf3a7694..49f39537c01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1470,12 +1470,12 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a41dee58608b1fc93779ea365edaa70ac9927e3335ae914b675be0fa063cd7" +checksum = "df5a0ba0d08af366cf235dbe8eb7226cced7a4fe502c98aa434ccf416defd746" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros 0.36.0", + "ra-ap-rustc_index_macros 0.37.0", "smallvec", ] @@ -1493,9 +1493,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbfe98def54c4337a2f7d8233850bd5d5349972b185fe8a0db2b979164b30ed8" +checksum = "1971ebf9a701e0e68387c264a32517dcb4861ad3a4862f2e2803c1121ade20d5" dependencies = [ "proc-macro2", "quote", @@ -1525,11 +1525,11 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5529bffec7530b4a3425640bfdfd9b95d87c4c620f740266c0de6572561aab4" +checksum = "2c3c0e7ca9c5bdc66e3b590688e237a22ac47a48e4eac7f46b05b2abbfaf0abd" dependencies = [ - "ra-ap-rustc_index 0.36.0", + "ra-ap-rustc_index 0.37.0", "rustc-hash", "rustc_apfloat", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 2b81f7b11b2..49c7d369190 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,7 +84,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.36.0", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.37.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 7f8fb7f4b52..c4329a7b82b 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -169,9 +169,9 @@ impl ExprValidator { return; } - let pattern_arena = Arena::new(); - let cx = MatchCheckCtx::new(self.owner.module(db.upcast()), self.owner, db, &pattern_arena); + let cx = MatchCheckCtx::new(self.owner.module(db.upcast()), self.owner, db); + let pattern_arena = Arena::new(); let mut m_arms = Vec::with_capacity(arms.len()); let mut has_lowering_errors = false; for arm in arms { @@ -196,8 +196,9 @@ impl ExprValidator { // If we had a NotUsefulMatchArm diagnostic, we could // check the usefulness of each pattern as we added it // to the matrix here. + let pat = self.lower_pattern(&cx, arm.pat, db, &body, &mut has_lowering_errors); let m_arm = pat_analysis::MatchArm { - pat: self.lower_pattern(&cx, arm.pat, db, &body, &mut has_lowering_errors), + pat: pattern_arena.alloc(pat), has_guard: arm.guard.is_some(), arm_data: (), }; @@ -223,7 +224,7 @@ impl ExprValidator { ValidityConstraint::ValidOnly, ) { Ok(report) => report, - Err(void) => match void {}, + Err(()) => return, }; // FIXME Report unreachable arms @@ -245,10 +246,10 @@ impl ExprValidator { db: &dyn HirDatabase, body: &Body, have_errors: &mut bool, - ) -> &'p DeconstructedPat<'p> { + ) -> DeconstructedPat<'p> { let mut patcx = match_check::PatCtxt::new(db, &self.infer, body); let pattern = patcx.lower_pattern(pat); - let pattern = cx.pattern_arena.alloc(cx.lower_pat(&pattern)); + let pattern = cx.lower_pat(&pattern); if !patcx.errors.is_empty() { *have_errors = true; } 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 712842372b6..e98a946a870 100644 --- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -1,6 +1,7 @@ //! Interface with `rustc_pattern_analysis`. use std::fmt; +use tracing::debug; use hir_def::{DefWithBodyId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId}; use rustc_hash::FxHashMap; @@ -11,7 +12,6 @@ use rustc_pattern_analysis::{ }; use smallvec::{smallvec, SmallVec}; use stdx::never; -use typed_arena::Arena; use crate::{ db::HirDatabase, @@ -26,7 +26,7 @@ use Constructor::*; // Re-export r-a-specific versions of all these types. pub(crate) type DeconstructedPat<'p> = - rustc_pattern_analysis::pat::DeconstructedPat<'p, MatchCheckCtx<'p>>; + rustc_pattern_analysis::pat::DeconstructedPat>; pub(crate) type MatchArm<'p> = rustc_pattern_analysis::MatchArm<'p, MatchCheckCtx<'p>>; pub(crate) type WitnessPat<'p> = rustc_pattern_analysis::pat::WitnessPat>; @@ -40,7 +40,6 @@ pub(crate) struct MatchCheckCtx<'p> { module: ModuleId, body: DefWithBodyId, pub(crate) db: &'p dyn HirDatabase, - pub(crate) pattern_arena: &'p Arena>, exhaustive_patterns: bool, min_exhaustive_patterns: bool, } @@ -52,17 +51,12 @@ pub(crate) struct PatData<'p> { } impl<'p> MatchCheckCtx<'p> { - pub(crate) fn new( - module: ModuleId, - body: DefWithBodyId, - db: &'p dyn HirDatabase, - pattern_arena: &'p Arena>, - ) -> Self { + pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'p dyn HirDatabase) -> Self { let def_map = db.crate_def_map(module.krate()); let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns"); let min_exhaustive_patterns = def_map.is_unstable_feature_enabled("min_exhaustive_patterns"); - Self { module, body, db, pattern_arena, exhaustive_patterns, min_exhaustive_patterns } + Self { module, body, db, exhaustive_patterns, min_exhaustive_patterns } } fn is_uninhabited(&self, ty: &Ty) -> bool { @@ -131,15 +125,15 @@ impl<'p> MatchCheckCtx<'p> { } pub(crate) fn lower_pat(&self, pat: &Pat) -> DeconstructedPat<'p> { - let singleton = |pat| std::slice::from_ref(self.pattern_arena.alloc(pat)); + let singleton = |pat| vec![pat]; let ctor; - let fields: &[_]; + let fields: Vec<_>; match pat.kind.as_ref() { PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; - fields = &[]; + fields = Vec::new(); } PatKind::Deref { subpattern } => { ctor = match pat.ty.kind(Interner) { @@ -157,7 +151,7 @@ impl<'p> MatchCheckCtx<'p> { match pat.ty.kind(Interner) { TyKind::Tuple(_, substs) => { ctor = Struct; - let mut wilds: SmallVec<[_; 2]> = substs + let mut wilds: Vec<_> = substs .iter(Interner) .map(|arg| arg.assert_ty_ref(Interner).clone()) .map(DeconstructedPat::wildcard) @@ -166,7 +160,7 @@ impl<'p> MatchCheckCtx<'p> { let idx: u32 = pat.field.into_raw().into(); wilds[idx as usize] = self.lower_pat(&pat.pattern); } - fields = self.pattern_arena.alloc_extend(wilds) + fields = wilds } TyKind::Adt(adt, substs) if is_box(self.db, adt.0) => { // The only legal patterns of type `Box` (outside `std`) are `_` and box @@ -216,33 +210,29 @@ impl<'p> MatchCheckCtx<'p> { field_id_to_id[field_idx as usize] = Some(i); ty }); - let mut wilds: SmallVec<[_; 2]> = - tys.map(DeconstructedPat::wildcard).collect(); + let mut wilds: Vec<_> = tys.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); } } - fields = self.pattern_arena.alloc_extend(wilds); + fields = wilds; } _ => { never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty); ctor = Wildcard; - fields = &[]; + fields = Vec::new(); } } } &PatKind::LiteralBool { value } => { ctor = Bool(value); - fields = &[]; + fields = Vec::new(); } PatKind::Or { pats } => { ctor = Or; - // Collect here because `Arena::alloc_extend` panics on reentrancy. - let subpats: SmallVec<[_; 2]> = - pats.iter().map(|pat| self.lower_pat(pat)).collect(); - fields = self.pattern_arena.alloc_extend(subpats); + fields = pats.iter().map(|pat| self.lower_pat(pat)).collect(); } } let data = PatData { db: self.db }; @@ -307,7 +297,7 @@ impl<'p> MatchCheckCtx<'p> { } impl<'p> TypeCx for MatchCheckCtx<'p> { - type Error = Void; + type Error = (); type Ty = Ty; type VariantIdx = EnumVariantId; type StrLit = Void; @@ -463,7 +453,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> { fn write_variant_name( f: &mut fmt::Formatter<'_>, - pat: &rustc_pattern_analysis::pat::DeconstructedPat<'_, Self>, + pat: &rustc_pattern_analysis::pat::DeconstructedPat, ) -> fmt::Result { let variant = pat.ty().as_adt().and_then(|(adt, _)| Self::variant_id_for_adt(pat.ctor(), adt)); @@ -485,8 +475,8 @@ impl<'p> TypeCx for MatchCheckCtx<'p> { Ok(()) } - fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { - panic!("{}", fmt) + fn bug(&self, fmt: fmt::Arguments<'_>) { + debug!("{}", fmt) } } diff --git a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 17dc679e055..7632fdf1d09 100644 --- a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -310,6 +310,24 @@ fn main() { ); } + #[test] + fn mismatched_types_issue_15883() { + // Check we don't panic. + check_diagnostics_no_bails( + r#" +//- minicore: option +fn main() { + match Some((true, false)) { + Some(true) | Some(false) => {} + // ^^^^ error: expected (bool, bool), found bool + // ^^^^^ error: expected (bool, bool), found bool + None => {} + } +} + "#, + ); + } + #[test] fn mismatched_types_in_or_patterns() { cov_mark::check_count!(validate_match_bailed_out, 2);