Skip to content

Commit 0d43b44

Browse files
committed
internal: Sync match checking algorithm with rustc
Original version: rust-lang/rust 68b76a483 2021-10-01
1 parent 13ec077 commit 0d43b44

File tree

7 files changed

+583
-868
lines changed

7 files changed

+583
-868
lines changed

Cargo.lock

+7-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir_ty/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ chalk-solve = { version = "0.71", default-features = false }
2121
chalk-ir = "0.71"
2222
chalk-recursive = { version = "0.71", default-features = false }
2323
la-arena = { version = "0.2.0", path = "../../lib/arena" }
24-
once_cell = { version = "1.5.0" }
24+
typed-arena = "2.0.1"
2525

2626
stdx = { path = "../stdx", version = "0.0.0" }
2727
hir_def = { path = "../hir_def", version = "0.0.0" }

crates/hir_ty/src/diagnostics/expr.rs

+20-27
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! through the body using inference results: mismatched arg counts, missing
33
//! fields, etc.
44
5-
use std::{cell::RefCell, sync::Arc};
5+
use std::sync::Arc;
66

77
use hir_def::{
88
expr::Statement, path::path, resolver::HasResolver, type_ref::Mutability, AssocItemId,
@@ -11,12 +11,14 @@ use hir_def::{
1111
use hir_expand::name;
1212
use itertools::Either;
1313
use rustc_hash::FxHashSet;
14+
use typed_arena::Arena;
1415

1516
use crate::{
1617
db::HirDatabase,
1718
diagnostics::match_check::{
1819
self,
19-
usefulness::{compute_match_usefulness, expand_pattern, MatchCheckCtx, PatternArena},
20+
deconstruct_pat::DeconstructedPat,
21+
usefulness::{compute_match_usefulness, MatchCheckCtx},
2022
},
2123
AdtId, InferenceResult, Interner, Ty, TyExt, TyKind,
2224
};
@@ -266,15 +268,19 @@ impl ExprValidator {
266268
) {
267269
let body = db.body(self.owner);
268270

269-
let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
271+
let match_expr_ty = &infer[match_expr];
272+
if match_expr_ty.is_unknown() {
270273
return;
271-
} else {
272-
&infer.type_of_expr[match_expr]
273-
};
274+
}
274275

275-
let pattern_arena = RefCell::new(PatternArena::new());
276+
let pattern_arena = Arena::new();
277+
let cx = MatchCheckCtx {
278+
module: self.owner.module(db.upcast()),
279+
db,
280+
pattern_arena: &pattern_arena,
281+
};
276282

277-
let mut m_arms = Vec::new();
283+
let mut m_arms = Vec::with_capacity(arms.len());
278284
let mut has_lowering_errors = false;
279285
for arm in arms {
280286
if let Some(pat_ty) = infer.type_of_pat.get(arm.pat) {
@@ -299,13 +305,7 @@ impl ExprValidator {
299305
// check the usefulness of each pattern as we added it
300306
// to the matrix here.
301307
let m_arm = match_check::MatchArm {
302-
pat: self.lower_pattern(
303-
arm.pat,
304-
&mut pattern_arena.borrow_mut(),
305-
db,
306-
&body,
307-
&mut has_lowering_errors,
308-
),
308+
pat: self.lower_pattern(&cx, arm.pat, db, &body, &mut has_lowering_errors),
309309
has_guard: arm.guard.is_some(),
310310
};
311311
m_arms.push(m_arm);
@@ -323,14 +323,7 @@ impl ExprValidator {
323323
return;
324324
}
325325

326-
let cx = MatchCheckCtx {
327-
module: self.owner.module(db.upcast()),
328-
match_expr,
329-
infer: &infer,
330-
db,
331-
pattern_arena: &pattern_arena,
332-
};
333-
let report = compute_match_usefulness(&cx, &m_arms);
326+
let report = compute_match_usefulness(&cx, &m_arms, match_expr_ty);
334327

335328
// FIXME Report unreacheble arms
336329
// https://github.com/rust-lang/rust/blob/25c15cdbe/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200-L201
@@ -343,17 +336,17 @@ impl ExprValidator {
343336
}
344337
}
345338

346-
fn lower_pattern(
339+
fn lower_pattern<'p>(
347340
&self,
341+
cx: &MatchCheckCtx<'_, 'p>,
348342
pat: PatId,
349-
pattern_arena: &mut PatternArena,
350343
db: &dyn HirDatabase,
351344
body: &Body,
352345
have_errors: &mut bool,
353-
) -> match_check::PatId {
346+
) -> &'p DeconstructedPat<'p> {
354347
let mut patcx = match_check::PatCtxt::new(db, &self.infer, body);
355348
let pattern = patcx.lower_pattern(pat);
356-
let pattern = pattern_arena.alloc(expand_pattern(pattern));
349+
let pattern = cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern));
357350
if !patcx.errors.is_empty() {
358351
*have_errors = true;
359352
}

crates/hir_ty/src/diagnostics/match_check.rs

+9-18
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,19 @@
55
//!
66
//! It is modeled on the rustc module `rustc_mir_build::thir::pattern`.
77
8-
mod deconstruct_pat;
98
mod pat_util;
109

10+
pub(crate) mod deconstruct_pat;
1111
pub(crate) mod usefulness;
1212

13-
use hir_def::{body::Body, EnumVariantId, LocalFieldId, VariantId};
14-
use la_arena::Idx;
13+
use hir_def::{body::Body, expr::PatId, EnumVariantId, LocalFieldId, VariantId};
1514

1615
use crate::{db::HirDatabase, InferenceResult, Interner, Substitution, Ty, TyKind};
1716

1817
use self::pat_util::EnumerateAndAdjustIterator;
1918

2019
pub(crate) use self::usefulness::MatchArm;
2120

22-
pub(crate) type PatId = Idx<Pat>;
23-
2421
#[derive(Clone, Debug)]
2522
pub(crate) enum PatternError {
2623
Unimplemented,
@@ -41,12 +38,6 @@ pub(crate) struct Pat {
4138
pub(crate) kind: Box<PatKind>,
4239
}
4340

44-
impl Pat {
45-
pub(crate) fn wildcard_from_ty(ty: Ty) -> Self {
46-
Pat { ty, kind: Box::new(PatKind::Wild) }
47-
}
48-
}
49-
5041
/// Close relative to `rustc_mir_build::thir::pattern::PatKind`
5142
#[derive(Clone, Debug, PartialEq)]
5243
pub(crate) enum PatKind {
@@ -100,7 +91,7 @@ impl<'a> PatCtxt<'a> {
10091
Self { db, infer, body, errors: Vec::new() }
10192
}
10293

103-
pub(crate) fn lower_pattern(&mut self, pat: hir_def::expr::PatId) -> Pat {
94+
pub(crate) fn lower_pattern(&mut self, pat: PatId) -> Pat {
10495
// XXX(iDawer): Collecting pattern adjustments feels imprecise to me.
10596
// When lowering of & and box patterns are implemented this should be tested
10697
// in a manner of `match_ergonomics_issue_9095` test.
@@ -116,7 +107,7 @@ impl<'a> PatCtxt<'a> {
116107
)
117108
}
118109

119-
fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat {
110+
fn lower_pattern_unadjusted(&mut self, pat: PatId) -> Pat {
120111
let mut ty = &self.infer[pat];
121112
let variant = self.infer.variant_resolution_for_pat(pat);
122113

@@ -189,7 +180,7 @@ impl<'a> PatCtxt<'a> {
189180

190181
fn lower_tuple_subpats(
191182
&mut self,
192-
pats: &[hir_def::expr::PatId],
183+
pats: &[PatId],
193184
expected_len: usize,
194185
ellipsis: Option<usize>,
195186
) -> Vec<FieldPat> {
@@ -207,17 +198,17 @@ impl<'a> PatCtxt<'a> {
207198
.collect()
208199
}
209200

210-
fn lower_patterns(&mut self, pats: &[hir_def::expr::PatId]) -> Vec<Pat> {
201+
fn lower_patterns(&mut self, pats: &[PatId]) -> Vec<Pat> {
211202
pats.iter().map(|&p| self.lower_pattern(p)).collect()
212203
}
213204

214-
fn lower_opt_pattern(&mut self, pat: Option<hir_def::expr::PatId>) -> Option<Pat> {
205+
fn lower_opt_pattern(&mut self, pat: Option<PatId>) -> Option<Pat> {
215206
pat.map(|p| self.lower_pattern(p))
216207
}
217208

218209
fn lower_variant_or_leaf(
219210
&mut self,
220-
pat: hir_def::expr::PatId,
211+
pat: PatId,
221212
ty: &Ty,
222213
subpatterns: Vec<FieldPat>,
223214
) -> PatKind {
@@ -244,7 +235,7 @@ impl<'a> PatCtxt<'a> {
244235
kind
245236
}
246237

247-
fn lower_path(&mut self, pat: hir_def::expr::PatId, _path: &hir_def::path::Path) -> Pat {
238+
fn lower_path(&mut self, pat: PatId, _path: &hir_def::path::Path) -> Pat {
248239
let ty = &self.infer[pat];
249240

250241
let pat_from_kind = |kind| Pat { ty: ty.clone(), kind: Box::new(kind) };

0 commit comments

Comments
 (0)