suggest fix for attempted integer identifier in patterns

This commit is contained in:
Ezra Shaw 2023-01-13 14:14:26 +13:00
parent 61a415be59
commit 1babece1e8
No known key found for this signature in database
GPG Key ID: 17CD5C2ADAE0D344
8 changed files with 99 additions and 4 deletions

View File

@ -364,3 +364,5 @@ mir_build_suggest_let_else = you might want to use `let else` to handle the {$co
[one] variant that isn't
*[other] variants that aren't
} matched
mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits

View File

@ -770,6 +770,8 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
#[subdiagnostic]
pub let_suggestion: Option<SuggestLet>,
#[subdiagnostic]
pub misc_suggestion: Option<MiscPatternSuggestion>,
#[subdiagnostic]
pub res_defined_here: Option<ResDefinedHere>,
}
@ -848,3 +850,16 @@ pub enum SuggestLet {
count: usize,
},
}
#[derive(Subdiagnostic)]
pub enum MiscPatternSuggestion {
#[suggestion(
mir_build_suggest_attempted_int_lit,
code = "_",
applicability = "maybe-incorrect"
)]
AttemptedIntegerLiteral {
#[primary_span]
start_span: Span,
},
}

View File

@ -6,8 +6,9 @@ use super::{PatCtxt, PatternError};
use crate::errors::*;
use hir::{ExprKind, PatKind};
use rustc_arena::TypedArena;
use rustc_ast::Mutability;
use rustc_ast::{LitKind, Mutability};
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
@ -389,7 +390,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
return;
}
let (inform, interpreted_as_const, res_defined_here,let_suggestion) =
let (inform, interpreted_as_const, res_defined_here,let_suggestion, misc_suggestion) =
if let hir::PatKind::Path(hir::QPath::Resolved(
None,
hir::Path {
@ -413,6 +414,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
}
},
None,
None,
)
} else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) {
let mut bindings = vec![];
@ -426,10 +428,19 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
let end_span = semi_span.shrink_to_lo();
let count = witnesses.len();
// If the pattern to match is an integer literal:
let int_suggestion = if
let PatKind::Lit(expr) = &pat.kind
&& bindings.is_empty()
&& let ExprKind::Lit(Spanned { node: LitKind::Int(_, _), span }) = expr.kind {
// Then give a suggestion, the user might've meant to create a binding instead.
Some(MiscPatternSuggestion::AttemptedIntegerLiteral { start_span: span.shrink_to_lo() })
} else { None };
let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }};
(sp.map(|_|Inform), None, None, Some(let_suggestion))
(sp.map(|_|Inform), None, None, Some(let_suggestion), int_suggestion)
} else{
(sp.map(|_|Inform), None, None, None)
(sp.map(|_|Inform), None, None, None, None)
};
let adt_defined_here = try {
@ -453,6 +464,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
_p: (),
pattern_ty,
let_suggestion,
misc_suggestion,
res_defined_here,
adt_defined_here,
});

View File

@ -11,6 +11,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
LL | A = { if let 0 = 0 { todo!() } 0 },
| ++ ~~~~~~~~~~~
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
LL | A = { let _0 = 0; 0 },
| +
error: aborting due to previous error

View File

@ -11,6 +11,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = [];
| ++ ~~~~~~~~~~~
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
LL | let x: [i32; { let _0 = 0; 0 }] = [];
| +
error: aborting due to previous error

View File

@ -11,6 +11,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
| ++ ~~~~~~~~~~~
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
LL | const X: i32 = { let _0 = 0; 0 };
| +
error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:8:23
@ -25,6 +29,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
| ++ ~~~~~~~~~~~
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
LL | static Y: i32 = { let _0 = 0; 0 };
| +
error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:13:26
@ -39,6 +47,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
| ++ ~~~~~~~~~~~
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
LL | const X: i32 = { let _0 = 0; 0 };
| +
error[E0005]: refutable pattern in local binding
--> $DIR/const-match-check.rs:19:26
@ -53,6 +65,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
| ++ ~~~~~~~~~~~
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
LL | const X: i32 = { let _0 = 0; 0 };
| +
error: aborting due to 4 previous errors

View File

@ -0,0 +1,7 @@
fn main() {
let 5 = 6;
//~^ error refutable pattern in local binding [E0005]
let x @ 5 = 6;
//~^ error refutable pattern in local binding [E0005]
}

View File

@ -0,0 +1,35 @@
error[E0005]: refutable pattern in local binding
--> $DIR/issue-106552.rs:2:9
|
LL | let 5 = 6;
| ^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered
|
= 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 5 = 6 { todo!() }
| ++ ~~~~~~~~~~~
help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
LL | let _5 = 6;
| +
error[E0005]: refutable pattern in local binding
--> $DIR/issue-106552.rs:5:9
|
LL | let x @ 5 = 6;
| ^^^^^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered
|
= 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 `let else` to handle the variants that aren't matched
|
LL | let x @ 5 = 6 else { todo!() };
| ++++++++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0005`.