From 4f97540432445c7e0dc4eb51e3ac5fd915d225ad Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 27 Feb 2023 20:50:01 +0000 Subject: [PATCH] Reinstate confusion note. --- compiler/rustc_mir_build/messages.ftl | 4 +- compiler/rustc_mir_build/src/errors.rs | 13 ------ .../src/thir/pattern/check_match.rs | 46 +++++++++++-------- tests/ui/consts/const-pattern-irrefutable.rs | 9 ++-- .../consts/const-pattern-irrefutable.stderr | 34 +++++++------- .../refutable-pattern-in-fn-arg.stderr | 4 ++ .../const-pat-non-exaustive-let-new-var.rs | 4 +- ...const-pat-non-exaustive-let-new-var.stderr | 10 ++-- 8 files changed, 63 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index c8172219267..f346cd48347 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -347,15 +347,13 @@ mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -mir_build_res_defined_here = {$res} defined here - mir_build_adt_defined_here = `{$ty}` defined here mir_build_variant_defined_here = not covered mir_build_interpreted_as_const = introduce a variable instead -mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as {$article} {$res} pattern, not a new variable +mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count -> [one] variant that isn't diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c67a002dce1..6a05f35bdf3 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -6,7 +6,6 @@ use rustc_errors::{ error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage, }; -use rustc_hir::def::Res; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::{self, Ty}; @@ -795,8 +794,6 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { pub let_suggestion: Option, #[subdiagnostic] pub misc_suggestion: Option, - #[subdiagnostic] - pub res_defined_here: Option, } #[derive(Subdiagnostic)] @@ -830,14 +827,6 @@ impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { } } -#[derive(Subdiagnostic)] -#[label(mir_build_res_defined_here)] -pub struct ResDefinedHere { - #[primary_span] - pub def_span: Span, - pub res: Res, -} - #[derive(Subdiagnostic)] #[suggestion( mir_build_interpreted_as_const, @@ -848,9 +837,7 @@ pub struct ResDefinedHere { pub struct InterpretedAsConst { #[primary_span] pub span: Span, - pub article: &'static str, pub variable: String, - pub res: Res, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b1f85f03989..4fb8e915220 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -424,29 +424,38 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let inform = sp.is_some().then_some(Inform); let mut let_suggestion = None; let mut misc_suggestion = None; - if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) { - let mut bindings= vec![]; - pat.each_binding(|name, _, _, _| { - bindings.push(name); - }); + let mut interpreted_as_const = None; + if let PatKind::Constant { .. } = pat.kind + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) + { + // If the pattern to match is an integer literal: + if snippet.chars().all(|c| c.is_digit(10)) { + // Then give a suggestion, the user might've meant to create a binding instead. + misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral { + start_span: pat.span.shrink_to_lo() + }); + } else if snippet.chars().all(|c| c.is_alphanumeric() || c == '_') { + interpreted_as_const = Some(InterpretedAsConst { + span: pat.span, + variable: snippet, + }); + } + } + + if let Some(span) = sp + && self.tcx.sess.source_map().is_span_accessible(span) + && interpreted_as_const.is_none() + { + let mut bindings = vec![]; + pat.each_binding(|name, _, _, _| bindings.push(name)); + let semi_span = span.shrink_to_hi(); let start_span = span.shrink_to_lo(); let end_span = semi_span.shrink_to_lo(); let count = witnesses.len(); - // If the pattern to match is an integer literal: - if bindings.is_empty() - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) - && snippet.chars().all(|c| c.is_digit(10)) - { - // Then give a suggestion, the user might've meant to create a binding instead. - misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral { - start_span: pat.span.shrink_to_lo() - }); - } - let_suggestion = Some(if bindings.is_empty() { - SuggestLet::If {start_span, semi_span, count } + SuggestLet::If { start_span, semi_span, count } } else { SuggestLet::Else { end_span, count } }); @@ -469,12 +478,11 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { origin, uncovered: Uncovered::new(pat.span, &cx, witnesses), inform, - interpreted_as_const: None, + interpreted_as_const, _p: (), pattern_ty, let_suggestion, misc_suggestion, - res_defined_here: None, adt_defined_here, }); } diff --git a/tests/ui/consts/const-pattern-irrefutable.rs b/tests/ui/consts/const-pattern-irrefutable.rs index d7d8e732839..61bdf57ffdb 100644 --- a/tests/ui/consts/const-pattern-irrefutable.rs +++ b/tests/ui/consts/const-pattern-irrefutable.rs @@ -12,14 +12,17 @@ fn main() { let a = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead let c = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead let d = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). } diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr index 956a97a476c..2aed68bdd64 100644 --- a/tests/ui/consts/const-pattern-irrefutable.stderr +++ b/tests/ui/consts/const-pattern-irrefutable.stderr @@ -2,43 +2,43 @@ error[E0005]: refutable pattern in local binding --> $DIR/const-pattern-irrefutable.rs:12:9 | LL | let a = 4; - | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `a_var` | = note: `let` bindings 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/ch18-02-refutability.html = note: the matched value is of type `u8` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let a = 4 { todo!() }; - | ++ +++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:16:9 + --> $DIR/const-pattern-irrefutable.rs:17:9 | LL | let c = 4; - | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `c_var` | = note: `let` bindings 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/ch18-02-refutability.html = note: the matched value is of type `u8` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let c = 4 { todo!() }; - | ++ +++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:20:9 + --> $DIR/const-pattern-irrefutable.rs:22:9 | LL | let d = 4; - | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `d_var` | = note: `let` bindings 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/ch18-02-refutability.html = note: the matched value is of type `u8` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let d = 4 { todo!() }; - | ++ +++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr index 55f0b2319fb..ab3f6f69fb1 100644 --- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr @@ -5,6 +5,10 @@ LL | let f = |3: isize| println!("hello"); | ^ pattern `_` not covered | = note: the matched value is of type `isize` +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | let f = |_3: isize| println!("hello"); + | + error: aborting due to previous error diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs index 0b7eb3ee605..af47ba8baa3 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs @@ -2,7 +2,9 @@ fn main() { let A = 3; //~^ ERROR refutable pattern in local binding //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead + //~| SUGGESTION A_var const A: i32 = 2; } diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr index b112e3a1175..9ee3e6eb2c8 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -2,15 +2,15 @@ error[E0005]: refutable pattern in local binding --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9 | LL | let A = 3; - | ^ patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered + | ^ + | | + | patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered + | missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `A_var` | = note: `let` bindings 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/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let A = 3 { todo!() }; - | ++ +++++++++++ error: aborting due to previous error