Rollup merge of #145827 - estebank:issue-51976, r=jackh726
On unused binding or binding not present in all patterns, suggest potential typo of unit struct/variant or const
When encountering an or-pattern with a binding not available in all patterns, look for consts and unit struct/variants that have similar names as the binding to detect typos.
```
error[E0408]: variable `Ban` is not bound in all patterns
--> $DIR/binding-typo.rs:22:9
|
LL | (Foo, _) | (Ban, Foo) => {}
| ^^^^^^^^ --- variable not in all patterns
| |
| pattern doesn't bind `Ban`
|
help: you might have meant to use the similarly named unit variant `Bar`
|
LL - (Foo, _) | (Ban, Foo) => {}
LL + (Foo, _) | (Bar, Foo) => {}
|
```
For items that are not in the immedate scope, suggest the full path for them:
```
error[E0408]: variable `Non` is not bound in all patterns
--> $DIR/binding-typo-2.rs:51:16
|
LL | (Non | Some(_))=> {}
| --- ^^^^^^^ pattern doesn't bind `Non`
| |
| variable not in all patterns
|
help: you might have meant to use the similarly named unit variant `None`
|
LL - (Non | Some(_))=> {}
LL + (core::option::Option::None | Some(_))=> {}
|
```
When encountering a typo in a pattern that gets interpreted as an unused binding, look for unit struct/variant of the same type as the binding:
```
error: unused variable: `Non`
--> $DIR/binding-typo-2.rs:36:9
|
LL | Non => {}
| ^^^
|
help: if this is intentional, prefix it with an underscore
|
LL | _Non => {}
| +
help: you might have meant to pattern match on the similarly named variant `None`
|
LL - Non => {}
LL + std::prelude::v1::None => {}
|
```
Suggest constant on unused binding in a pattern
```
error: unused variable: `Batery`
--> $DIR/binding-typo-2.rs:110:9
|
LL | Batery => {}
| ^^^^^^
|
help: if this is intentional, prefix it with an underscore
|
LL | _Batery => {}
| +
help: you might have meant to pattern match on the similarly named constant `Battery`
|
LL | Battery => {}
| +
```
Fix rust-lang/rust#51976.
This commit is contained in:
commit
3a6ae1167f
22 changed files with 911 additions and 83 deletions
|
|
@ -687,6 +687,7 @@ passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
|
|||
|
||||
passes_unused_var_remove_field = unused variable: `{$name}`
|
||||
passes_unused_var_remove_field_suggestion = try removing the field
|
||||
passes_unused_var_typo = you might have meant to pattern match on the similarly named {$kind} `{$item_name}`
|
||||
|
||||
passes_unused_variable_args_in_macro = `{$name}` is captured in macro and introduced a unused variable
|
||||
|
||||
|
|
|
|||
|
|
@ -1367,6 +1367,22 @@ pub(crate) struct UnusedVarRemoveFieldSugg {
|
|||
#[note]
|
||||
pub(crate) struct UnusedVarAssignedOnly {
|
||||
pub name: String,
|
||||
#[subdiagnostic]
|
||||
pub typo: Option<PatternTypo>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
passes_unused_var_typo,
|
||||
style = "verbose",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
pub(crate) struct PatternTypo {
|
||||
#[suggestion_part(code = "{code}")]
|
||||
pub span: Span,
|
||||
pub code: String,
|
||||
pub item_name: String,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -1434,6 +1450,8 @@ pub(crate) struct UnusedVariableTryPrefix {
|
|||
#[subdiagnostic]
|
||||
pub sugg: UnusedVariableSugg,
|
||||
pub name: String,
|
||||
#[subdiagnostic]
|
||||
pub typo: Option<PatternTypo>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
|
|||
|
|
@ -95,8 +95,10 @@ use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, find_attr};
|
|||
use rustc_index::IndexVec;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
|
@ -1688,6 +1690,51 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
let is_assigned =
|
||||
if ln == self.exit_ln { false } else { self.assigned_on_exit(ln, var) };
|
||||
|
||||
let mut typo = None;
|
||||
for (hir_id, _, span) in &hir_ids_and_spans {
|
||||
let ty = self.typeck_results.node_type(*hir_id);
|
||||
if let ty::Adt(adt, _) = ty.peel_refs().kind() {
|
||||
let name = Symbol::intern(&name);
|
||||
let adt_def = self.ir.tcx.adt_def(adt.did());
|
||||
let variant_names: Vec<_> = adt_def
|
||||
.variants()
|
||||
.iter()
|
||||
.filter(|v| matches!(v.ctor, Some((CtorKind::Const, _))))
|
||||
.map(|v| v.name)
|
||||
.collect();
|
||||
if let Some(name) = find_best_match_for_name(&variant_names, name, None)
|
||||
&& let Some(variant) = adt_def.variants().iter().find(|v| {
|
||||
v.name == name && matches!(v.ctor, Some((CtorKind::Const, _)))
|
||||
})
|
||||
{
|
||||
typo = Some(errors::PatternTypo {
|
||||
span: *span,
|
||||
code: with_no_trimmed_paths!(self.ir.tcx.def_path_str(variant.def_id)),
|
||||
kind: self.ir.tcx.def_descr(variant.def_id).to_string(),
|
||||
item_name: variant.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if typo.is_none() {
|
||||
for (hir_id, _, span) in &hir_ids_and_spans {
|
||||
let ty = self.typeck_results.node_type(*hir_id);
|
||||
// Look for consts of the same type with similar names as well, not just unit
|
||||
// structs and variants.
|
||||
for def_id in self.ir.tcx.hir_body_owners() {
|
||||
if let DefKind::Const = self.ir.tcx.def_kind(def_id)
|
||||
&& self.ir.tcx.type_of(def_id).instantiate_identity() == ty
|
||||
{
|
||||
typo = Some(errors::PatternTypo {
|
||||
span: *span,
|
||||
code: with_no_trimmed_paths!(self.ir.tcx.def_path_str(def_id)),
|
||||
kind: "constant".to_string(),
|
||||
item_name: self.ir.tcx.item_name(def_id).to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if is_assigned {
|
||||
self.ir.tcx.emit_node_span_lint(
|
||||
lint::builtin::UNUSED_VARIABLES,
|
||||
|
|
@ -1696,7 +1743,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
.into_iter()
|
||||
.map(|(_, _, ident_span)| ident_span)
|
||||
.collect::<Vec<_>>(),
|
||||
errors::UnusedVarAssignedOnly { name },
|
||||
errors::UnusedVarAssignedOnly { name, typo },
|
||||
)
|
||||
} else if can_remove {
|
||||
let spans = hir_ids_and_spans
|
||||
|
|
@ -1788,6 +1835,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
name,
|
||||
sugg,
|
||||
string_interp: suggestions,
|
||||
typo,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,6 +470,8 @@ resolve_variable_bound_with_different_mode =
|
|||
.label = bound in different ways
|
||||
.first_binding_span = first binding
|
||||
|
||||
resolve_variable_is_a_typo = you might have meant to use the similarly named previously used binding `{$typo}`
|
||||
|
||||
resolve_variable_is_not_bound_in_all_patterns =
|
||||
variable `{$name}` is not bound in all patterns
|
||||
|
||||
|
|
|
|||
|
|
@ -661,8 +661,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
|
||||
let BindingError { name, target, origin, could_be_path } = binding_error;
|
||||
|
||||
let target_sp = target.iter().copied().collect::<Vec<_>>();
|
||||
let origin_sp = origin.iter().copied().collect::<Vec<_>>();
|
||||
let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();
|
||||
target_sp.sort();
|
||||
target_sp.dedup();
|
||||
let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();
|
||||
origin_sp.sort();
|
||||
origin_sp.dedup();
|
||||
|
||||
let msp = MultiSpan::from_spans(target_sp.clone());
|
||||
let mut err = self
|
||||
|
|
@ -671,8 +675,35 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
for sp in target_sp {
|
||||
err.subdiagnostic(errors::PatternDoesntBindName { span: sp, name });
|
||||
}
|
||||
for sp in origin_sp {
|
||||
err.subdiagnostic(errors::VariableNotInAllPatterns { span: sp });
|
||||
for sp in &origin_sp {
|
||||
err.subdiagnostic(errors::VariableNotInAllPatterns { span: *sp });
|
||||
}
|
||||
let mut suggested_typo = false;
|
||||
if !target.iter().all(|pat| matches!(pat.kind, ast::PatKind::Ident(..)))
|
||||
&& !origin.iter().all(|(_, pat)| matches!(pat.kind, ast::PatKind::Ident(..)))
|
||||
{
|
||||
// The check above is so that when we encounter `match foo { (a | b) => {} }`,
|
||||
// we don't suggest `(a | a) => {}`, which would never be what the user wants.
|
||||
let mut target_visitor = BindingVisitor::default();
|
||||
for pat in &target {
|
||||
target_visitor.visit_pat(pat);
|
||||
}
|
||||
target_visitor.identifiers.sort();
|
||||
target_visitor.identifiers.dedup();
|
||||
let mut origin_visitor = BindingVisitor::default();
|
||||
for (_, pat) in &origin {
|
||||
origin_visitor.visit_pat(pat);
|
||||
}
|
||||
origin_visitor.identifiers.sort();
|
||||
origin_visitor.identifiers.dedup();
|
||||
// Find if the binding could have been a typo
|
||||
if let Some(typo) =
|
||||
find_best_match_for_name(&target_visitor.identifiers, name.name, None)
|
||||
&& !origin_visitor.identifiers.contains(&typo)
|
||||
{
|
||||
err.subdiagnostic(errors::PatternBindingTypo { spans: origin_sp, typo });
|
||||
suggested_typo = true;
|
||||
}
|
||||
}
|
||||
if could_be_path {
|
||||
let import_suggestions = self.lookup_import_candidates(
|
||||
|
|
@ -693,10 +724,86 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
},
|
||||
);
|
||||
|
||||
if import_suggestions.is_empty() {
|
||||
if import_suggestions.is_empty() && !suggested_typo {
|
||||
let kinds = [
|
||||
DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
|
||||
DefKind::Ctor(CtorOf::Struct, CtorKind::Const),
|
||||
DefKind::Const,
|
||||
DefKind::AssocConst,
|
||||
];
|
||||
let mut local_names = vec![];
|
||||
self.add_module_candidates(
|
||||
parent_scope.module,
|
||||
&mut local_names,
|
||||
&|res| matches!(res, Res::Def(_, _)),
|
||||
None,
|
||||
);
|
||||
let local_names: FxHashSet<_> = local_names
|
||||
.into_iter()
|
||||
.filter_map(|s| match s.res {
|
||||
Res::Def(_, def_id) => Some(def_id),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut local_suggestions = vec![];
|
||||
let mut suggestions = vec![];
|
||||
for kind in kinds {
|
||||
if let Some(suggestion) = self.early_lookup_typo_candidate(
|
||||
ScopeSet::All(Namespace::ValueNS),
|
||||
&parent_scope,
|
||||
name,
|
||||
&|res: Res| match res {
|
||||
Res::Def(k, _) => k == kind,
|
||||
_ => false,
|
||||
},
|
||||
) && let Res::Def(kind, mut def_id) = suggestion.res
|
||||
{
|
||||
if let DefKind::Ctor(_, _) = kind {
|
||||
def_id = self.tcx.parent(def_id);
|
||||
}
|
||||
let kind = kind.descr(def_id);
|
||||
if local_names.contains(&def_id) {
|
||||
// The item is available in the current scope. Very likely to
|
||||
// be a typo. Don't use the full path.
|
||||
local_suggestions.push((
|
||||
suggestion.candidate,
|
||||
suggestion.candidate.to_string(),
|
||||
kind,
|
||||
));
|
||||
} else {
|
||||
suggestions.push((
|
||||
suggestion.candidate,
|
||||
self.def_path_str(def_id),
|
||||
kind,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
let suggestions = if !local_suggestions.is_empty() {
|
||||
// There is at least one item available in the current scope that is a
|
||||
// likely typo. We only show those.
|
||||
local_suggestions
|
||||
} else {
|
||||
suggestions
|
||||
};
|
||||
for (name, sugg, kind) in suggestions {
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
format!(
|
||||
"you might have meant to use the similarly named {kind} `{name}`",
|
||||
),
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
suggested_typo = true;
|
||||
}
|
||||
}
|
||||
if import_suggestions.is_empty() && !suggested_typo {
|
||||
let help_msg = format!(
|
||||
"if you meant to match on a variant or a `const` item, consider \
|
||||
making the path in the pattern qualified: `path::to::ModOrType::{name}`",
|
||||
"if you meant to match on a unit struct, unit variant or a `const` \
|
||||
item, consider making the path in the pattern qualified: \
|
||||
`path::to::ModOrType::{name}`",
|
||||
);
|
||||
err.span_help(span, help_msg);
|
||||
}
|
||||
|
|
@ -1016,6 +1123,39 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
.emit()
|
||||
}
|
||||
|
||||
fn def_path_str(&self, mut def_id: DefId) -> String {
|
||||
// We can't use `def_path_str` in resolve.
|
||||
let mut path = vec![def_id];
|
||||
while let Some(parent) = self.tcx.opt_parent(def_id) {
|
||||
def_id = parent;
|
||||
path.push(def_id);
|
||||
if def_id.is_top_level_module() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We will only suggest importing directly if it is accessible through that path.
|
||||
path.into_iter()
|
||||
.rev()
|
||||
.map(|def_id| {
|
||||
self.tcx
|
||||
.opt_item_name(def_id)
|
||||
.map(|name| {
|
||||
match (
|
||||
def_id.is_top_level_module(),
|
||||
def_id.is_local(),
|
||||
self.tcx.sess.edition(),
|
||||
) {
|
||||
(true, true, Edition::Edition2015) => String::new(),
|
||||
(true, true, _) => kw::Crate.to_string(),
|
||||
(true, false, _) | (false, _, _) => name.to_string(),
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| "_".to_string())
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("::")
|
||||
}
|
||||
|
||||
pub(crate) fn add_scope_set_candidates(
|
||||
&mut self,
|
||||
suggestions: &mut Vec<TypoSuggestion>,
|
||||
|
|
@ -3396,7 +3536,7 @@ impl UsePlacementFinder {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
|
||||
impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
|
||||
fn visit_crate(&mut self, c: &Crate) {
|
||||
if self.target_module == CRATE_NODE_ID {
|
||||
let inject = c.spans.inject_use_span;
|
||||
|
|
@ -3424,6 +3564,22 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct BindingVisitor {
|
||||
identifiers: Vec<Symbol>,
|
||||
spans: FxHashMap<Symbol, Vec<Span>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for BindingVisitor {
|
||||
fn visit_pat(&mut self, pat: &ast::Pat) {
|
||||
if let ast::PatKind::Ident(_, ident, _) = pat.kind {
|
||||
self.identifiers.push(ident.name);
|
||||
self.spans.entry(ident.name).or_default().push(ident.span);
|
||||
}
|
||||
visit::walk_pat(self, pat);
|
||||
}
|
||||
}
|
||||
|
||||
fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
|
||||
for item in items {
|
||||
if let ItemKind::Use(..) = item.kind
|
||||
|
|
|
|||
|
|
@ -986,6 +986,18 @@ pub(crate) struct VariableNotInAllPatterns {
|
|||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
resolve_variable_is_a_typo,
|
||||
applicability = "maybe-incorrect",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub(crate) struct PatternBindingTypo {
|
||||
#[suggestion_part(code = "{typo}")]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
pub(crate) typo: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(resolve_name_defined_multiple_time)]
|
||||
#[note]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
use std::assert_matches::debug_assert_matches;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::mem::{replace, swap, take};
|
||||
|
||||
|
|
@ -3682,31 +3681,30 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
// 2) Record any missing bindings or binding mode inconsistencies.
|
||||
for (map_outer, pat_outer) in not_never_pats.iter() {
|
||||
// Check against all arms except for the same pattern which is always self-consistent.
|
||||
let inners = not_never_pats
|
||||
.iter()
|
||||
.filter(|(_, pat)| pat.id != pat_outer.id)
|
||||
.flat_map(|(map, _)| map);
|
||||
let inners = not_never_pats.iter().filter(|(_, pat)| pat.id != pat_outer.id);
|
||||
|
||||
for (&name, binding_inner) in inners {
|
||||
match map_outer.get(&name) {
|
||||
None => {
|
||||
// The inner binding is missing in the outer.
|
||||
let binding_error =
|
||||
missing_vars.entry(name).or_insert_with(|| BindingError {
|
||||
name,
|
||||
origin: BTreeSet::new(),
|
||||
target: BTreeSet::new(),
|
||||
could_be_path: name.as_str().starts_with(char::is_uppercase),
|
||||
});
|
||||
binding_error.origin.insert(binding_inner.span);
|
||||
binding_error.target.insert(pat_outer.span);
|
||||
}
|
||||
Some(binding_outer) => {
|
||||
if binding_outer.annotation != binding_inner.annotation {
|
||||
// The binding modes in the outer and inner bindings differ.
|
||||
inconsistent_vars
|
||||
.entry(name)
|
||||
.or_insert((binding_inner.span, binding_outer.span));
|
||||
for (map, pat) in inners {
|
||||
for (&name, binding_inner) in map {
|
||||
match map_outer.get(&name) {
|
||||
None => {
|
||||
// The inner binding is missing in the outer.
|
||||
let binding_error =
|
||||
missing_vars.entry(name).or_insert_with(|| BindingError {
|
||||
name,
|
||||
origin: Default::default(),
|
||||
target: Default::default(),
|
||||
could_be_path: name.as_str().starts_with(char::is_uppercase),
|
||||
});
|
||||
binding_error.origin.push((binding_inner.span, (***pat).clone()));
|
||||
binding_error.target.push((***pat_outer).clone());
|
||||
}
|
||||
Some(binding_outer) => {
|
||||
if binding_outer.annotation != binding_inner.annotation {
|
||||
// The binding modes in the outer and inner bindings differ.
|
||||
inconsistent_vars
|
||||
.entry(name)
|
||||
.or_insert((binding_inner.span, binding_outer.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3719,7 +3717,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
v.could_be_path = false;
|
||||
}
|
||||
self.report_error(
|
||||
*v.origin.iter().next().unwrap(),
|
||||
v.origin.iter().next().unwrap().0,
|
||||
ResolutionError::VariableNotBoundInPattern(v, self.parent_scope),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -230,8 +230,8 @@ enum Used {
|
|||
#[derive(Debug)]
|
||||
struct BindingError {
|
||||
name: Ident,
|
||||
origin: BTreeSet<Span>,
|
||||
target: BTreeSet<Span>,
|
||||
origin: Vec<(Span, ast::Pat)>,
|
||||
target: Vec<ast::Pat>,
|
||||
could_be_path: bool,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//@ run-rustfix
|
||||
#![deny(unused_assignments, unused_variables)]
|
||||
#![deny(unused_assignments)]
|
||||
#![allow(unused_mut)]
|
||||
struct Object;
|
||||
|
||||
|
|
@ -8,15 +8,15 @@ fn change_object(object: &mut Object) { //~ HELP you might have meant to mutate
|
|||
*object = object2; //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn change_object2(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||
//~^ HELP you might have meant to mutate
|
||||
fn change_object2(object: &mut Object) {
|
||||
//~^ HELP you might have meant to mutate
|
||||
let object2 = Object;
|
||||
*object = object2;
|
||||
//~^ ERROR `object2` does not live long enough
|
||||
//~| ERROR value assigned to `object` is never read
|
||||
}
|
||||
|
||||
fn change_object3(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||
fn change_object3(object: &mut Object) {
|
||||
//~^ HELP you might have meant to mutate
|
||||
let mut object2 = Object; //~ HELP consider changing this to be mutable
|
||||
*object = object2;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//@ run-rustfix
|
||||
#![deny(unused_assignments, unused_variables)]
|
||||
#![deny(unused_assignments)]
|
||||
#![allow(unused_mut)]
|
||||
struct Object;
|
||||
|
||||
|
|
@ -8,15 +8,15 @@ fn change_object(mut object: &Object) { //~ HELP you might have meant to mutate
|
|||
object = object2; //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn change_object2(mut object: &Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||
//~^ HELP you might have meant to mutate
|
||||
fn change_object2(mut object: &Object) {
|
||||
//~^ HELP you might have meant to mutate
|
||||
let object2 = Object;
|
||||
object = &object2;
|
||||
//~^ ERROR `object2` does not live long enough
|
||||
//~| ERROR value assigned to `object` is never read
|
||||
}
|
||||
|
||||
fn change_object3(mut object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||
fn change_object3(mut object: &mut Object) {
|
||||
//~^ HELP you might have meant to mutate
|
||||
let object2 = Object; //~ HELP consider changing this to be mutable
|
||||
object = &mut object2;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ LL | object = &object2;
|
|||
note: the lint level is defined here
|
||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:2:9
|
||||
|
|
||||
LL | #![deny(unused_assignments, unused_variables)]
|
||||
LL | #![deny(unused_assignments)]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
|
||||
|
|
||||
|
|
@ -33,19 +33,6 @@ LL | let object2 = Object;
|
|||
LL ~ *object = object2;
|
||||
|
|
||||
|
||||
error: variable `object` is assigned to, but never used
|
||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:11:23
|
||||
|
|
||||
LL | fn change_object2(mut object: &Object) {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: consider using `_object` instead
|
||||
note: the lint level is defined here
|
||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:2:29
|
||||
|
|
||||
LL | #![deny(unused_assignments, unused_variables)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0597]: `object2` does not live long enough
|
||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:14:13
|
||||
|
|
||||
|
|
@ -77,14 +64,6 @@ LL | let object2 = Object;
|
|||
LL ~ *object = object2;
|
||||
|
|
||||
|
||||
error: variable `object` is assigned to, but never used
|
||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:19:23
|
||||
|
|
||||
LL | fn change_object3(mut object: &mut Object) {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: consider using `_object` instead
|
||||
|
||||
error[E0596]: cannot borrow `object2` as mutable, as it is not declared as mutable
|
||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:22:14
|
||||
|
|
||||
|
|
@ -96,7 +75,7 @@ help: consider changing this to be mutable
|
|||
LL | let mut object2 = Object;
|
||||
| +++
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0596, E0597.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ warning: unused variable: `Foo`
|
|||
--> $DIR/lint-uppercase-variables.rs:22:9
|
||||
|
|
||||
LL | Foo => {}
|
||||
| ^^^ help: if this is intentional, prefix it with an underscore: `_Foo`
|
||||
| ^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-uppercase-variables.rs:1:9
|
||||
|
|
@ -24,12 +24,29 @@ note: the lint level is defined here
|
|||
LL | #![warn(unused)]
|
||||
| ^^^^^^
|
||||
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | _Foo => {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named variant `Foo`
|
||||
|
|
||||
LL | foo::Foo::Foo => {}
|
||||
| ++++++++++
|
||||
|
||||
warning: unused variable: `Foo`
|
||||
--> $DIR/lint-uppercase-variables.rs:28:9
|
||||
|
|
||||
LL | let Foo = foo::Foo::Foo;
|
||||
| ^^^ help: if this is intentional, prefix it with an underscore: `_Foo`
|
||||
| ^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | let _Foo = foo::Foo::Foo;
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named variant `Foo`
|
||||
|
|
||||
LL | let foo::Foo::Foo = foo::Foo::Foo;
|
||||
| ++++++++++
|
||||
|
||||
error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
|
||||
--> $DIR/lint-uppercase-variables.rs:33:17
|
||||
|
|
@ -41,7 +58,16 @@ warning: unused variable: `Foo`
|
|||
--> $DIR/lint-uppercase-variables.rs:33:17
|
||||
|
|
||||
LL | fn in_param(Foo: foo::Foo) {}
|
||||
| ^^^ help: if this is intentional, prefix it with an underscore: `_Foo`
|
||||
| ^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | fn in_param(_Foo: foo::Foo) {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named variant `Foo`
|
||||
|
|
||||
LL | fn in_param(foo::Foo::Foo: foo::Foo) {}
|
||||
| ++++++++++
|
||||
|
||||
error: structure field `X` should have a snake case name
|
||||
--> $DIR/lint-uppercase-variables.rs:10:5
|
||||
|
|
|
|||
122
tests/ui/or-patterns/binding-typo-2.rs
Normal file
122
tests/ui/or-patterns/binding-typo-2.rs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Issue #51976
|
||||
#![deny(unused_variables)] //~ NOTE: the lint level is defined here
|
||||
enum Lol {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
const Bat: () = ();
|
||||
const Battery: () = ();
|
||||
struct Bay;
|
||||
|
||||
fn foo(x: (Lol, Lol)) {
|
||||
use Lol::*;
|
||||
match &x {
|
||||
(Foo, Bar) | (Ban, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named previously used binding `Bar`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
//~| ERROR: variable `Ban` is assigned to, but never used
|
||||
//~| NOTE: consider using `_Ban` instead
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
_ => {}
|
||||
}
|
||||
match &x {
|
||||
(Foo, _) | (Ban, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named unit variant `Bar`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
//~| ERROR: variable `Ban` is assigned to, but never used
|
||||
//~| NOTE: consider using `_Ban` instead
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
_ => {}
|
||||
}
|
||||
match Some(42) {
|
||||
Some(_) => {}
|
||||
Non => {}
|
||||
//~^ ERROR: unused variable: `Non`
|
||||
//~| HELP: if this is intentional, prefix it with an underscore
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
}
|
||||
match Some(42) {
|
||||
Some(_) => {}
|
||||
Non | None => {}
|
||||
//~^ ERROR: unused variable: `Non`
|
||||
//~| HELP: if this is intentional, prefix it with an underscore
|
||||
//~| ERROR: variable `Non` is not bound in all patterns [E0408]
|
||||
//~| NOTE: pattern doesn't bind `Non`
|
||||
//~| NOTE: variable not in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named unit variant `None`
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
}
|
||||
match Some(42) {
|
||||
Non | Some(_) => {}
|
||||
//~^ ERROR: unused variable: `Non`
|
||||
//~| HELP: if this is intentional, prefix it with an underscore
|
||||
//~| ERROR: variable `Non` is not bound in all patterns [E0408]
|
||||
//~| NOTE: pattern doesn't bind `Non`
|
||||
//~| NOTE: variable not in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named unit variant `None`
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
}
|
||||
}
|
||||
fn bar(x: (Lol, Lol)) {
|
||||
use Lol::*;
|
||||
use ::Bat;
|
||||
use ::Bay;
|
||||
match &x {
|
||||
(Foo, _) | (Ban, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named unit variant `Bar`
|
||||
//~| HELP: you might have meant to use the similarly named unit struct `Bay`
|
||||
//~| HELP: you might have meant to use the similarly named constant `Bat`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
//~| ERROR: variable `Ban` is assigned to, but never used
|
||||
//~| NOTE: consider using `_Ban` instead
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
fn baz(x: (Lol, Lol)) {
|
||||
use Lol::*;
|
||||
use Bat;
|
||||
match &x {
|
||||
(Foo, _) | (Ban, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named unit variant `Bar`
|
||||
//~| HELP: you might have meant to use the similarly named constant `Bat`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
//~| ERROR: variable `Ban` is assigned to, but never used
|
||||
//~| NOTE: consider using `_Ban` instead
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
_ => {}
|
||||
}
|
||||
match &x {
|
||||
(Ban, _) => {}
|
||||
//~^ ERROR: unused variable: `Ban`
|
||||
//~| HELP: if this is intentional, prefix it with an underscore
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
}
|
||||
match Bay {
|
||||
Ban => {}
|
||||
//~^ ERROR: unused variable: `Ban`
|
||||
//~| HELP: if this is intentional, prefix it with an underscore
|
||||
//~| HELP: you might have meant to pattern match on the similarly named
|
||||
}
|
||||
match () {
|
||||
Batery => {}
|
||||
//~^ ERROR: unused variable: `Batery`
|
||||
//~| HELP: if this is intentional, prefix it with an underscore
|
||||
//~| HELP: you might have meant to pattern match on the similarly named constant
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use Lol::*;
|
||||
foo((Foo, Bar));
|
||||
bar((Foo, Bar));
|
||||
baz((Foo, Bar));
|
||||
}
|
||||
254
tests/ui/or-patterns/binding-typo-2.stderr
Normal file
254
tests/ui/or-patterns/binding-typo-2.stderr
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
error[E0408]: variable `Ban` is not bound in all patterns
|
||||
--> $DIR/binding-typo-2.rs:14:9
|
||||
|
|
||||
LL | (Foo, Bar) | (Ban, Foo) => {}
|
||||
| ^^^^^^^^^^ --- variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `Ban`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `Bar`
|
||||
|
|
||||
LL - (Foo, Bar) | (Ban, Foo) => {}
|
||||
LL + (Foo, Bar) | (Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error[E0408]: variable `Ban` is not bound in all patterns
|
||||
--> $DIR/binding-typo-2.rs:25:9
|
||||
|
|
||||
LL | (Foo, _) | (Ban, Foo) => {}
|
||||
| ^^^^^^^^ --- variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `Ban`
|
||||
|
|
||||
help: you might have meant to use the similarly named unit variant `Bar`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error[E0408]: variable `Non` is not bound in all patterns
|
||||
--> $DIR/binding-typo-2.rs:44:15
|
||||
|
|
||||
LL | Non | None => {}
|
||||
| --- ^^^^ pattern doesn't bind `Non`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named unit variant `None`
|
||||
|
|
||||
LL - Non | None => {}
|
||||
LL + core::option::Option::None | None => {}
|
||||
|
|
||||
|
||||
error[E0408]: variable `Non` is not bound in all patterns
|
||||
--> $DIR/binding-typo-2.rs:54:15
|
||||
|
|
||||
LL | Non | Some(_) => {}
|
||||
| --- ^^^^^^^ pattern doesn't bind `Non`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named unit variant `None`
|
||||
|
|
||||
LL - Non | Some(_) => {}
|
||||
LL + core::option::Option::None | Some(_) => {}
|
||||
|
|
||||
|
||||
error[E0408]: variable `Ban` is not bound in all patterns
|
||||
--> $DIR/binding-typo-2.rs:69:9
|
||||
|
|
||||
LL | (Foo, _) | (Ban, Foo) => {}
|
||||
| ^^^^^^^^ --- variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `Ban`
|
||||
|
|
||||
help: you might have meant to use the similarly named unit variant `Bar`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Bar, Foo) => {}
|
||||
|
|
||||
help: you might have meant to use the similarly named unit struct `Bay`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Bay, Foo) => {}
|
||||
|
|
||||
help: you might have meant to use the similarly named constant `Bat`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Bat, Foo) => {}
|
||||
|
|
||||
|
||||
error[E0408]: variable `Ban` is not bound in all patterns
|
||||
--> $DIR/binding-typo-2.rs:86:9
|
||||
|
|
||||
LL | (Foo, _) | (Ban, Foo) => {}
|
||||
| ^^^^^^^^ --- variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `Ban`
|
||||
|
|
||||
help: you might have meant to use the similarly named unit variant `Bar`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Bar, Foo) => {}
|
||||
|
|
||||
help: you might have meant to use the similarly named constant `Bat`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Bat, Foo) => {}
|
||||
|
|
||||
|
||||
error: variable `Ban` is assigned to, but never used
|
||||
--> $DIR/binding-typo-2.rs:14:23
|
||||
|
|
||||
LL | (Foo, Bar) | (Ban, Foo) => {}
|
||||
| ^^^
|
||||
|
|
||||
= note: consider using `_Ban` instead
|
||||
note: the lint level is defined here
|
||||
--> $DIR/binding-typo-2.rs:2:9
|
||||
|
|
||||
LL | #![deny(unused_variables)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
help: you might have meant to pattern match on the similarly named variant `Bar`
|
||||
|
|
||||
LL - (Foo, Bar) | (Ban, Foo) => {}
|
||||
LL + (Foo, Bar) | (Lol::Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error: variable `Ban` is assigned to, but never used
|
||||
--> $DIR/binding-typo-2.rs:25:21
|
||||
|
|
||||
LL | (Foo, _) | (Ban, Foo) => {}
|
||||
| ^^^
|
||||
|
|
||||
= note: consider using `_Ban` instead
|
||||
help: you might have meant to pattern match on the similarly named variant `Bar`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Lol::Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error: unused variable: `Non`
|
||||
--> $DIR/binding-typo-2.rs:37:9
|
||||
|
|
||||
LL | Non => {}
|
||||
| ^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | _Non => {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named variant `None`
|
||||
|
|
||||
LL - Non => {}
|
||||
LL + std::prelude::v1::None => {}
|
||||
|
|
||||
|
||||
error: unused variable: `Non`
|
||||
--> $DIR/binding-typo-2.rs:44:9
|
||||
|
|
||||
LL | Non | None => {}
|
||||
| ^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | _Non | None => {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named variant `None`
|
||||
|
|
||||
LL - Non | None => {}
|
||||
LL + std::prelude::v1::None | None => {}
|
||||
|
|
||||
|
||||
error: unused variable: `Non`
|
||||
--> $DIR/binding-typo-2.rs:54:9
|
||||
|
|
||||
LL | Non | Some(_) => {}
|
||||
| ^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | _Non | Some(_) => {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named variant `None`
|
||||
|
|
||||
LL - Non | Some(_) => {}
|
||||
LL + std::prelude::v1::None | Some(_) => {}
|
||||
|
|
||||
|
||||
error: variable `Ban` is assigned to, but never used
|
||||
--> $DIR/binding-typo-2.rs:69:21
|
||||
|
|
||||
LL | (Foo, _) | (Ban, Foo) => {}
|
||||
| ^^^
|
||||
|
|
||||
= note: consider using `_Ban` instead
|
||||
help: you might have meant to pattern match on the similarly named variant `Bar`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Lol::Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error: variable `Ban` is assigned to, but never used
|
||||
--> $DIR/binding-typo-2.rs:86:21
|
||||
|
|
||||
LL | (Foo, _) | (Ban, Foo) => {}
|
||||
| ^^^
|
||||
|
|
||||
= note: consider using `_Ban` instead
|
||||
help: you might have meant to pattern match on the similarly named variant `Bar`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Lol::Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error: unused variable: `Ban`
|
||||
--> $DIR/binding-typo-2.rs:98:10
|
||||
|
|
||||
LL | (Ban, _) => {}
|
||||
| ^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | (_Ban, _) => {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named variant `Bar`
|
||||
|
|
||||
LL - (Ban, _) => {}
|
||||
LL + (Lol::Bar, _) => {}
|
||||
|
|
||||
|
||||
error: unused variable: `Ban`
|
||||
--> $DIR/binding-typo-2.rs:104:9
|
||||
|
|
||||
LL | Ban => {}
|
||||
| ^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | _Ban => {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named struct `Bay`
|
||||
|
|
||||
LL - Ban => {}
|
||||
LL + Bay => {}
|
||||
|
|
||||
|
||||
error: unused variable: `Batery`
|
||||
--> $DIR/binding-typo-2.rs:110:9
|
||||
|
|
||||
LL | Batery => {}
|
||||
| ^^^^^^
|
||||
|
|
||||
help: if this is intentional, prefix it with an underscore
|
||||
|
|
||||
LL | _Batery => {}
|
||||
| +
|
||||
help: you might have meant to pattern match on the similarly named constant `Battery`
|
||||
|
|
||||
LL | Battery => {}
|
||||
| +
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0408`.
|
||||
32
tests/ui/or-patterns/binding-typo.fixed
Normal file
32
tests/ui/or-patterns/binding-typo.fixed
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Issue #51976
|
||||
//@ run-rustfix
|
||||
#![allow(unused_variables)] // allowed so we don't get overlapping suggestions
|
||||
enum Lol {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
fn foo(x: (Lol, Lol)) {
|
||||
use Lol::*;
|
||||
match &x {
|
||||
(Foo, Bar) | (Bar, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named previously used binding `Bar`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
_ => {}
|
||||
}
|
||||
match &x {
|
||||
(Foo, _) | (Bar, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named unit variant `Bar`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use Lol::*;
|
||||
foo((Foo, Bar));
|
||||
}
|
||||
32
tests/ui/or-patterns/binding-typo.rs
Normal file
32
tests/ui/or-patterns/binding-typo.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Issue #51976
|
||||
//@ run-rustfix
|
||||
#![allow(unused_variables)] // allowed so we don't get overlapping suggestions
|
||||
enum Lol {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
fn foo(x: (Lol, Lol)) {
|
||||
use Lol::*;
|
||||
match &x {
|
||||
(Foo, Bar) | (Ban, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named previously used binding `Bar`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
_ => {}
|
||||
}
|
||||
match &x {
|
||||
(Foo, _) | (Ban, Foo) => {}
|
||||
//~^ ERROR: variable `Ban` is not bound in all patterns
|
||||
//~| HELP: you might have meant to use the similarly named unit variant `Bar`
|
||||
//~| NOTE: pattern doesn't bind `Ban`
|
||||
//~| NOTE: variable not in all patterns
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use Lol::*;
|
||||
foo((Foo, Bar));
|
||||
}
|
||||
31
tests/ui/or-patterns/binding-typo.stderr
Normal file
31
tests/ui/or-patterns/binding-typo.stderr
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
error[E0408]: variable `Ban` is not bound in all patterns
|
||||
--> $DIR/binding-typo.rs:12:9
|
||||
|
|
||||
LL | (Foo, Bar) | (Ban, Foo) => {}
|
||||
| ^^^^^^^^^^ --- variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `Ban`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `Bar`
|
||||
|
|
||||
LL - (Foo, Bar) | (Ban, Foo) => {}
|
||||
LL + (Foo, Bar) | (Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error[E0408]: variable `Ban` is not bound in all patterns
|
||||
--> $DIR/binding-typo.rs:20:9
|
||||
|
|
||||
LL | (Foo, _) | (Ban, Foo) => {}
|
||||
| ^^^^^^^^ --- variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `Ban`
|
||||
|
|
||||
help: you might have meant to use the similarly named unit variant `Bar`
|
||||
|
|
||||
LL - (Foo, _) | (Ban, Foo) => {}
|
||||
LL + (Foo, _) | (Bar, Foo) => {}
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0408`.
|
||||
|
|
@ -86,6 +86,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| ^^^^^^^ - variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `c`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `a`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(a, b) | B(a), d) | B(e)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:47:22
|
||||
|
|
@ -94,6 +100,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| - ^^^^ pattern doesn't bind `a`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(c, b) | B(c), d) | B(e)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `b` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:47:22
|
||||
|
|
@ -102,6 +114,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| - ^^^^ pattern doesn't bind `b`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(a, c) | B(c), d) | B(e)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `e` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:47:10
|
||||
|
|
@ -110,6 +128,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `e`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(a, b) | B(c), d) | B(c)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:47:33
|
||||
|
|
@ -118,6 +142,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| - ^^^^ pattern doesn't bind `a`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `e`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(e, b) | B(c), d) | B(e)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `b` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:47:33
|
||||
|
|
@ -126,6 +156,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| - ^^^^ pattern doesn't bind `b`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `e`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(a, e) | B(c), d) | B(e)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `c` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:47:33
|
||||
|
|
@ -134,6 +170,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| - ^^^^ pattern doesn't bind `c`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `e`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(a, b) | B(e), d) | B(e)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `d` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:47:33
|
||||
|
|
@ -142,6 +184,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
|||
| - ^^^^ pattern doesn't bind `d`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `e`
|
||||
|
|
||||
LL - let (A(A(a, b) | B(c), d) | B(e)) = Y;
|
||||
LL + let (A(A(a, b) | B(c), e) | B(e)) = Y;
|
||||
|
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:63:29
|
||||
|
|
@ -158,6 +206,12 @@ LL | A(_, a) |
|
|||
| ^^^^^^^ pattern doesn't bind `b`
|
||||
LL | B(b),
|
||||
| - variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `a`
|
||||
|
|
||||
LL - B(b),
|
||||
LL + B(a),
|
||||
|
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:71:21
|
||||
|
|
@ -166,6 +220,12 @@ LL | A(_, a) |
|
|||
| - variable not in all patterns
|
||||
LL | B(b),
|
||||
| ^^^^ pattern doesn't bind `a`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `b`
|
||||
|
|
||||
LL - A(_, a) |
|
||||
LL + A(_, b) |
|
||||
|
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:74:17
|
||||
|
|
@ -202,6 +262,12 @@ LL | B(b),
|
|||
...
|
||||
LL | V3(c),
|
||||
| ^^^^^ pattern doesn't bind `b`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL - B(b),
|
||||
LL + B(c),
|
||||
|
|
||||
|
||||
error[E0408]: variable `c` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:59:13
|
||||
|
|
@ -223,6 +289,12 @@ LL | | ) |
|
|||
| |_____________^ pattern doesn't bind `c`
|
||||
LL | V3(c),
|
||||
| - variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `a`
|
||||
|
|
||||
LL - V3(c),
|
||||
LL + V3(a),
|
||||
|
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/missing-bindings.rs:78:13
|
||||
|
|
@ -235,6 +307,15 @@ LL | A(_, a) |
|
|||
...
|
||||
LL | V3(c),
|
||||
| ^^^^^ pattern doesn't bind `a`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL ~ B(Ok(a) | Err(c))
|
||||
LL | ) |
|
||||
LL | V2(
|
||||
LL | A(
|
||||
LL ~ A(_, c) |
|
||||
|
|
||||
|
||||
error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `check_handling_of_paths::bar::foo`
|
||||
--> $DIR/missing-bindings.rs:19:18
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@ LL | ((Ok(x) if y) | (Err(y) if x),) => x && y,
|
|||
| ^^^^^^^^^^^^ - variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `y`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `x`
|
||||
|
|
||||
LL - ((Ok(x) if y) | (Err(y) if x),) => x && y,
|
||||
LL + ((Ok(x) if y) | (Err(x) if x),) => x && y,
|
||||
|
|
||||
|
||||
error[E0408]: variable `x` is not bound in all patterns
|
||||
--> $DIR/name-resolution.rs:37:25
|
||||
|
|
@ -13,6 +19,12 @@ LL | ((Ok(x) if y) | (Err(y) if x),) => x && y,
|
|||
| - ^^^^^^^^^^^^^ pattern doesn't bind `x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `y`
|
||||
|
|
||||
LL - ((Ok(x) if y) | (Err(y) if x),) => x && y,
|
||||
LL + ((Ok(y) if y) | (Err(y) if x),) => x && y,
|
||||
|
|
||||
|
||||
error[E0408]: variable `x` is not bound in all patterns
|
||||
--> $DIR/name-resolution.rs:63:28
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ pub mod m {
|
|||
fn main() {
|
||||
let y = 1;
|
||||
match y {
|
||||
a | b => {} //~ ERROR variable `a` is not bound in all patterns
|
||||
//~| ERROR variable `b` is not bound in all patterns
|
||||
a | b => {} //~ ERROR variable `a` is not bound in all patterns
|
||||
//~| ERROR variable `b` is not bound in all patterns
|
||||
}
|
||||
|
||||
let x = (E::A, E::B);
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
error[E0408]: variable `b` is not bound in all patterns
|
||||
--> $DIR/resolve-inconsistent-names.rs:13:8
|
||||
--> $DIR/resolve-inconsistent-names.rs:13:9
|
||||
|
|
||||
LL | a | b => {}
|
||||
| ^ - variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `b`
|
||||
LL | a | b => {}
|
||||
| ^ - variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `b`
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/resolve-inconsistent-names.rs:13:12
|
||||
--> $DIR/resolve-inconsistent-names.rs:13:13
|
||||
|
|
||||
LL | a | b => {}
|
||||
| - ^ pattern doesn't bind `a`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
LL | a | b => {}
|
||||
| - ^ pattern doesn't bind `a`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0408]: variable `c` is not bound in all patterns
|
||||
--> $DIR/resolve-inconsistent-names.rs:19:9
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
|
|||
| | | pattern doesn't bind `b`
|
||||
| | variable not in all patterns
|
||||
| pattern doesn't bind `b`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL - T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
|
||||
LL + T::T1(a, d) | T::T2(d, c) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
|
||||
|
|
||||
|
||||
error[E0408]: variable `c` is not bound in all patterns
|
||||
--> $DIR/issue-39698.rs:10:9
|
||||
|
|
@ -17,6 +23,12 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
|
|||
| | | variable not in all patterns
|
||||
| | pattern doesn't bind `c`
|
||||
| pattern doesn't bind `c`
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `d`
|
||||
|
|
||||
LL - T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
|
||||
LL + T::T1(a, d) | T::T2(d, b) | T::T3(d) | T::T4(a) => { println!("{:?}", a); }
|
||||
|
|
||||
|
||||
error[E0408]: variable `a` is not bound in all patterns
|
||||
--> $DIR/issue-39698.rs:10:23
|
||||
|
|
@ -27,6 +39,12 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
|
|||
| | | pattern doesn't bind `a`
|
||||
| | pattern doesn't bind `a`
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL - T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
|
||||
LL + T::T1(c, d) | T::T2(d, b) | T::T3(c) | T::T4(c) => { println!("{:?}", a); }
|
||||
|
|
||||
|
||||
error[E0408]: variable `d` is not bound in all patterns
|
||||
--> $DIR/issue-39698.rs:10:37
|
||||
|
|
@ -37,6 +55,12 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
|
|||
| | | pattern doesn't bind `d`
|
||||
| | variable not in all patterns
|
||||
| variable not in all patterns
|
||||
|
|
||||
help: you might have meant to use the similarly named previously used binding `c`
|
||||
|
|
||||
LL - T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
|
||||
LL + T::T1(a, c) | T::T2(c, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
|
||||
|
|
||||
|
||||
error[E0381]: used binding `a` is possibly-uninitialized
|
||||
--> $DIR/issue-39698.rs:10:79
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue