Skip to content

Commit

Permalink
internal: Sync match checking algorithm with rustc
Browse files Browse the repository at this point in the history
Original version: rust-lang/rust  68b76a483 2021-10-01
  • Loading branch information
iDawer committed Oct 7, 2021
1 parent 13ec077 commit 0d43b44
Show file tree
Hide file tree
Showing 7 changed files with 583 additions and 868 deletions.
8 changes: 7 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/hir_ty/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ chalk-solve = { version = "0.71", default-features = false }
chalk-ir = "0.71"
chalk-recursive = { version = "0.71", default-features = false }
la-arena = { version = "0.2.0", path = "../../lib/arena" }
once_cell = { version = "1.5.0" }
typed-arena = "2.0.1"

stdx = { path = "../stdx", version = "0.0.0" }
hir_def = { path = "../hir_def", version = "0.0.0" }
Expand Down
47 changes: 20 additions & 27 deletions crates/hir_ty/src/diagnostics/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! through the body using inference results: mismatched arg counts, missing
//! fields, etc.

use std::{cell::RefCell, sync::Arc};
use std::sync::Arc;

use hir_def::{
expr::Statement, path::path, resolver::HasResolver, type_ref::Mutability, AssocItemId,
Expand All @@ -11,12 +11,14 @@ use hir_def::{
use hir_expand::name;
use itertools::Either;
use rustc_hash::FxHashSet;
use typed_arena::Arena;

use crate::{
db::HirDatabase,
diagnostics::match_check::{
self,
usefulness::{compute_match_usefulness, expand_pattern, MatchCheckCtx, PatternArena},
deconstruct_pat::DeconstructedPat,
usefulness::{compute_match_usefulness, MatchCheckCtx},
},
AdtId, InferenceResult, Interner, Ty, TyExt, TyKind,
};
Expand Down Expand Up @@ -266,15 +268,19 @@ impl ExprValidator {
) {
let body = db.body(self.owner);

let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
let match_expr_ty = &infer[match_expr];
if match_expr_ty.is_unknown() {
return;
} else {
&infer.type_of_expr[match_expr]
};
}

let pattern_arena = RefCell::new(PatternArena::new());
let pattern_arena = Arena::new();
let cx = MatchCheckCtx {
module: self.owner.module(db.upcast()),
db,
pattern_arena: &pattern_arena,
};

let mut m_arms = Vec::new();
let mut m_arms = Vec::with_capacity(arms.len());
let mut has_lowering_errors = false;
for arm in arms {
if let Some(pat_ty) = infer.type_of_pat.get(arm.pat) {
Expand All @@ -299,13 +305,7 @@ impl ExprValidator {
// check the usefulness of each pattern as we added it
// to the matrix here.
let m_arm = match_check::MatchArm {
pat: self.lower_pattern(
arm.pat,
&mut pattern_arena.borrow_mut(),
db,
&body,
&mut has_lowering_errors,
),
pat: self.lower_pattern(&cx, arm.pat, db, &body, &mut has_lowering_errors),
has_guard: arm.guard.is_some(),
};
m_arms.push(m_arm);
Expand All @@ -323,14 +323,7 @@ impl ExprValidator {
return;
}

let cx = MatchCheckCtx {
module: self.owner.module(db.upcast()),
match_expr,
infer: &infer,
db,
pattern_arena: &pattern_arena,
};
let report = compute_match_usefulness(&cx, &m_arms);
let report = compute_match_usefulness(&cx, &m_arms, match_expr_ty);

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

fn lower_pattern(
fn lower_pattern<'p>(
&self,
cx: &MatchCheckCtx<'_, 'p>,
pat: PatId,
pattern_arena: &mut PatternArena,
db: &dyn HirDatabase,
body: &Body,
have_errors: &mut bool,
) -> match_check::PatId {
) -> &'p DeconstructedPat<'p> {
let mut patcx = match_check::PatCtxt::new(db, &self.infer, body);
let pattern = patcx.lower_pattern(pat);
let pattern = pattern_arena.alloc(expand_pattern(pattern));
let pattern = cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern));
if !patcx.errors.is_empty() {
*have_errors = true;
}
Expand Down
27 changes: 9 additions & 18 deletions crates/hir_ty/src/diagnostics/match_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,19 @@
//!
//! It is modeled on the rustc module `rustc_mir_build::thir::pattern`.

mod deconstruct_pat;
mod pat_util;

pub(crate) mod deconstruct_pat;
pub(crate) mod usefulness;

use hir_def::{body::Body, EnumVariantId, LocalFieldId, VariantId};
use la_arena::Idx;
use hir_def::{body::Body, expr::PatId, EnumVariantId, LocalFieldId, VariantId};

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

use self::pat_util::EnumerateAndAdjustIterator;

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

pub(crate) type PatId = Idx<Pat>;

#[derive(Clone, Debug)]
pub(crate) enum PatternError {
Unimplemented,
Expand All @@ -41,12 +38,6 @@ pub(crate) struct Pat {
pub(crate) kind: Box<PatKind>,
}

impl Pat {
pub(crate) fn wildcard_from_ty(ty: Ty) -> Self {
Pat { ty, kind: Box::new(PatKind::Wild) }
}
}

/// Close relative to `rustc_mir_build::thir::pattern::PatKind`
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum PatKind {
Expand Down Expand Up @@ -100,7 +91,7 @@ impl<'a> PatCtxt<'a> {
Self { db, infer, body, errors: Vec::new() }
}

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

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

Expand Down Expand Up @@ -189,7 +180,7 @@ impl<'a> PatCtxt<'a> {

fn lower_tuple_subpats(
&mut self,
pats: &[hir_def::expr::PatId],
pats: &[PatId],
expected_len: usize,
ellipsis: Option<usize>,
) -> Vec<FieldPat> {
Expand All @@ -207,17 +198,17 @@ impl<'a> PatCtxt<'a> {
.collect()
}

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

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

fn lower_variant_or_leaf(
&mut self,
pat: hir_def::expr::PatId,
pat: PatId,
ty: &Ty,
subpatterns: Vec<FieldPat>,
) -> PatKind {
Expand All @@ -244,7 +235,7 @@ impl<'a> PatCtxt<'a> {
kind
}

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

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

0 comments on commit 0d43b44

Please sign in to comment.