Skip to content

Commit ee1f824

Browse files
committed
internal: Sync match checking algorithm with rustc
Original version: rust-lang/rust 68b76a483 2021-10-01
1 parent 9efa355 commit ee1f824

File tree

7 files changed

+583
-866
lines changed

7 files changed

+583
-866
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir_ty/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ chalk-ir = "0.74"
2323
chalk-recursive = { version = "0.74", default-features = false }
2424
la-arena = { version = "0.3.0", path = "../../lib/arena" }
2525
once_cell = { version = "1.5.0" }
26+
typed-arena = "2.0.1"
2627

2728
stdx = { path = "../stdx", version = "0.0.0" }
2829
hir_def = { path = "../hir_def", version = "0.0.0" }

crates/hir_ty/src/diagnostics/expr.rs

Lines changed: 20 additions & 27 deletions
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
};
@@ -262,15 +264,19 @@ impl ExprValidator {
262264
) {
263265
let body = db.body(self.owner);
264266

265-
let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
267+
let match_expr_ty = &infer[match_expr];
268+
if match_expr_ty.is_unknown() {
266269
return;
267-
} else {
268-
&infer.type_of_expr[match_expr]
269-
};
270+
}
270271

271-
let pattern_arena = RefCell::new(PatternArena::new());
272+
let pattern_arena = Arena::new();
273+
let cx = MatchCheckCtx {
274+
module: self.owner.module(db.upcast()),
275+
db,
276+
pattern_arena: &pattern_arena,
277+
};
272278

273-
let mut m_arms = Vec::new();
279+
let mut m_arms = Vec::with_capacity(arms.len());
274280
let mut has_lowering_errors = false;
275281
for arm in arms {
276282
if let Some(pat_ty) = infer.type_of_pat.get(arm.pat) {
@@ -295,13 +301,7 @@ impl ExprValidator {
295301
// check the usefulness of each pattern as we added it
296302
// to the matrix here.
297303
let m_arm = match_check::MatchArm {
298-
pat: self.lower_pattern(
299-
arm.pat,
300-
&mut pattern_arena.borrow_mut(),
301-
db,
302-
&body,
303-
&mut has_lowering_errors,
304-
),
304+
pat: self.lower_pattern(&cx, arm.pat, db, &body, &mut has_lowering_errors),
305305
has_guard: arm.guard.is_some(),
306306
};
307307
m_arms.push(m_arm);
@@ -319,14 +319,7 @@ impl ExprValidator {
319319
return;
320320
}
321321

322-
let cx = MatchCheckCtx {
323-
module: self.owner.module(db.upcast()),
324-
match_expr,
325-
infer: &infer,
326-
db,
327-
pattern_arena: &pattern_arena,
328-
};
329-
let report = compute_match_usefulness(&cx, &m_arms);
322+
let report = compute_match_usefulness(&cx, &m_arms, match_expr_ty);
330323

331324
// FIXME Report unreacheble arms
332325
// https://github.com/rust-lang/rust/blob/25c15cdbe/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200-L201
@@ -339,17 +332,17 @@ impl ExprValidator {
339332
}
340333
}
341334

342-
fn lower_pattern(
335+
fn lower_pattern<'p>(
343336
&self,
337+
cx: &MatchCheckCtx<'_, 'p>,
344338
pat: PatId,
345-
pattern_arena: &mut PatternArena,
346339
db: &dyn HirDatabase,
347340
body: &Body,
348341
have_errors: &mut bool,
349-
) -> match_check::PatId {
342+
) -> &'p DeconstructedPat<'p> {
350343
let mut patcx = match_check::PatCtxt::new(db, &self.infer, body);
351344
let pattern = patcx.lower_pattern(pat);
352-
let pattern = pattern_arena.alloc(expand_pattern(pattern));
345+
let pattern = cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern));
353346
if !patcx.errors.is_empty() {
354347
*have_errors = true;
355348
}

crates/hir_ty/src/diagnostics/match_check.rs

Lines changed: 9 additions & 18 deletions
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)