Reinstate confusion note.

This commit is contained in:
Camille GILLOT 2023-02-27 20:50:01 +00:00
parent 4d8ed585f2
commit 4f97540432
8 changed files with 63 additions and 61 deletions

View file

@ -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

View file

@ -6,7 +6,6 @@
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<SuggestLet>,
#[subdiagnostic]
pub misc_suggestion: Option<MiscPatternSuggestion>,
#[subdiagnostic]
pub res_defined_here: Option<ResDefinedHere>,
}
#[derive(Subdiagnostic)]
@ -830,14 +827,6 @@ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
}
}
#[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)]

View file

@ -424,29 +424,38 @@ fn check_irrefutable(&self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
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 @@ fn check_irrefutable(&self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
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,
});
}

View file

@ -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).
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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