Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,12 +1241,14 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
pub(crate) misc_suggestion: Option<MiscPatternSuggestion>,
}

#[derive(Subdiagnostic)]
#[derive(Subdiagnostic, Debug)]
#[note(
"`let` bindings require an \"irrefutable pattern\", like a `struct` or an `enum` with only one variant"
"{$descr} require an \"irrefutable pattern\", like a `struct` or an `enum` with only one variant"
)]
#[note("for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html")]
pub(crate) struct Inform;
pub(crate) struct Inform {
pub(crate) descr: &'static str,
}

#[derive(Subdiagnostic)]
#[label(
Expand Down
29 changes: 26 additions & 3 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err

for param in thir.params.iter() {
if let Some(ref pattern) = param.pat {
visitor.check_binding_is_irrefutable(pattern, origin, None, None);
visitor.check_binding_is_irrefutable(pattern, origin, None, None, None);
}
}
visitor.error
Expand Down Expand Up @@ -436,7 +436,29 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
assert!(self.let_source != LetSource::None);
let scrut = scrutinee.map(|id| &self.thir[id]);
if let LetSource::PlainLet = self.let_source {
self.check_binding_is_irrefutable(pat, "local binding", scrut, Some(span));
// `lhs = rhs` destructuring assignments are lowered to a `let` tagged
// `AssignDesugar`; report them as assignments, not `let` bindings (#157553).
if let hir::Node::LetStmt(&hir::LetStmt {
source: hir::LocalSource::AssignDesugar,
..
}) = self.tcx.hir_node(self.hir_source)
{
self.check_binding_is_irrefutable(
pat,
"assignment",
Some(Inform { descr: "destructuring assignments" }),
scrut,
None,
);
} else {
self.check_binding_is_irrefutable(
pat,
"local binding",
Some(Inform { descr: "`let` bindings" }),
scrut,
Some(span),
);
}
} else if let Ok(Irrefutable) = self.is_let_irrefutable(pat, scrut) {
if span.from_expansion() {
self.lint_single_let(span, None, None);
Expand Down Expand Up @@ -541,6 +563,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
"`for` loop binding",
None,
None,
None,
);
} else {
// span after scrutinee, or after `.match`. That is, the braces, arms,
Expand Down Expand Up @@ -645,6 +668,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
&mut self,
pat: &'p Pat<'tcx>,
origin: &str,
inform: Option<Inform>,
scrut: Option<&Expr<'tcx>>,
sp: Option<Span>,
) {
Expand All @@ -657,7 +681,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
return;
}

let inform = sp.is_some().then_some(Inform);
let mut let_suggestion = None;
let mut misc_suggestion = None;
let mut interpreted_as_const = None;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
fn main() {
None = Some(3);
//~^ ERROR refutable pattern in local binding
//~^ ERROR refutable pattern in assignment
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
error[E0005]: refutable pattern in local binding
error[E0005]: refutable pattern in assignment
--> $DIR/non-exhaustive-destructure.rs:2:5
|
LL | None = Some(3);
| ^^^^ pattern `Some(_)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: destructuring assignments require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
= note: the matched value is of type `Option<i32>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | if None = Some(3) { todo!() };
| ++ +++++++++++

error: aborting due to 1 previous error

Expand Down
11 changes: 11 additions & 0 deletions tests/ui/destructuring-assignment/refutable-enum-assignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Regression test for <https://github.com/rust-lang/rust/issues/157553>.

enum Foo {
One,
Two,
}

fn main() {
Foo::One = Foo::One;
//~^ ERROR refutable pattern in assignment
}
21 changes: 21 additions & 0 deletions tests/ui/destructuring-assignment/refutable-enum-assignment.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0005]: refutable pattern in assignment
--> $DIR/refutable-enum-assignment.rs:9:5
|
LL | Foo::One = Foo::One;
| ^^^^^^^^ pattern `Foo::Two` not covered
|
= note: destructuring assignments require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
note: `Foo` defined here
--> $DIR/refutable-enum-assignment.rs:3:6
|
LL | enum Foo {
| ^^^
LL | One,
LL | Two,
| --- not covered
= note: the matched value is of type `Foo`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0005`.
Loading