Auto merge of #108504 - cjgillot:thir-pattern, r=compiler-errors,Nilstrieb
Check pattern refutability on THIR The current `check_match` query is based on HIR, but partially re-lowers HIR into THIR. This PR proposed to use the results of the `thir_body` query to check matches, instead of re-building THIR. Most of the diagnostic changes are spans getting shorter, or commas/semicolons not getting removed. This PR degrades the diagnostic for confusing constants in patterns (`let A = foo()` where `A` resolves to a `const A` somewhere): it does not point ot the definition of `const A` any more.
This commit is contained in:
commit
0534655d9b
106 changed files with 1058 additions and 1499 deletions
|
@ -94,7 +94,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn dep_kind_info(&self, dep_kind: DepKind) -> &DepKindStruct<'tcx> {
|
||||
&self.query_kinds[dep_kind as usize]
|
||||
fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> {
|
||||
&self.query_kinds[dk as usize]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2001,6 +2001,13 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
}
|
||||
|
||||
impl BorrowKind {
|
||||
pub fn mutability(&self) -> Mutability {
|
||||
match *self {
|
||||
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not,
|
||||
BorrowKind::Mut { .. } => Mutability::Mut,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allows_two_phase_borrow(&self) -> bool {
|
||||
match *self {
|
||||
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
|
||||
|
|
|
@ -1114,9 +1114,9 @@ rustc_queries! {
|
|||
desc { "converting literal to mir constant" }
|
||||
}
|
||||
|
||||
query check_match(key: DefId) {
|
||||
desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
query check_match(key: LocalDefId) {
|
||||
desc { |tcx| "match-checking `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||
cache_on_disk_if { true }
|
||||
}
|
||||
|
||||
/// Performs part of the privacy check and computes effective visibilities.
|
||||
|
|
|
@ -227,6 +227,9 @@ pub enum StmtKind<'tcx> {
|
|||
|
||||
/// The lint level for this `let` statement.
|
||||
lint_level: LintLevel,
|
||||
|
||||
/// Span of the `let <PAT> = <INIT>` part.
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -594,6 +597,55 @@ impl<'tcx> Pat<'tcx> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
|
||||
/// `match foo() { Some(a) => (), None => () }`
|
||||
pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) {
|
||||
self.walk_always(|p| {
|
||||
if let PatKind::Binding { name, mode, ty, .. } = p.kind {
|
||||
f(name, mode, ty, p.span);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Walk the pattern in left-to-right order.
|
||||
///
|
||||
/// If `it(pat)` returns `false`, the children are not visited.
|
||||
pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
|
||||
self.walk_(&mut it)
|
||||
}
|
||||
|
||||
fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
|
||||
if !it(self) {
|
||||
return;
|
||||
}
|
||||
|
||||
use PatKind::*;
|
||||
match &self.kind {
|
||||
Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {}
|
||||
AscribeUserType { subpattern, .. }
|
||||
| Binding { subpattern: Some(subpattern), .. }
|
||||
| Deref { subpattern } => subpattern.walk_(it),
|
||||
Leaf { subpatterns } | Variant { subpatterns, .. } => {
|
||||
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
|
||||
}
|
||||
Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
|
||||
Array { box ref prefix, ref slice, box ref suffix }
|
||||
| Slice { box ref prefix, ref slice, box ref suffix } => {
|
||||
prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Walk the pattern in left-to-right order.
|
||||
///
|
||||
/// If you always want to recurse, prefer this method over `walk`.
|
||||
pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
|
||||
self.walk(|p| {
|
||||
it(p);
|
||||
true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
|
||||
|
@ -879,7 +931,7 @@ mod size_asserts {
|
|||
static_assert_size!(ExprKind<'_>, 40);
|
||||
static_assert_size!(Pat<'_>, 72);
|
||||
static_assert_size!(PatKind<'_>, 56);
|
||||
static_assert_size!(Stmt<'_>, 48);
|
||||
static_assert_size!(StmtKind<'_>, 40);
|
||||
static_assert_size!(Stmt<'_>, 56);
|
||||
static_assert_size!(StmtKind<'_>, 48);
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
|
|
@ -175,6 +175,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
|
|||
ref pattern,
|
||||
lint_level: _,
|
||||
else_block,
|
||||
span: _,
|
||||
} => {
|
||||
if let Some(init) = initializer {
|
||||
visitor.visit_expr(&visitor.thir()[*init]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue