librustc: Forbid identifiers that shadow in the same pattern in let
bindings and function arguments. Issue #14581. To fix code that this breaks, give the pattern identifiers different names. [breaking-change]
This commit is contained in:
parent
f0f9095f1d
commit
c23748c59c
2 changed files with 46 additions and 42 deletions
|
@ -3812,9 +3812,10 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
Some(declaration) => {
|
Some(declaration) => {
|
||||||
for argument in declaration.inputs.iter() {
|
for argument in declaration.inputs.iter() {
|
||||||
|
let mut bindings_list = HashMap::new();
|
||||||
this.resolve_pattern(&*argument.pat,
|
this.resolve_pattern(&*argument.pat,
|
||||||
ArgumentIrrefutableMode,
|
ArgumentIrrefutableMode,
|
||||||
None);
|
&mut bindings_list);
|
||||||
|
|
||||||
this.resolve_type(&*argument.ty);
|
this.resolve_type(&*argument.ty);
|
||||||
|
|
||||||
|
@ -4045,7 +4046,10 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the pattern.
|
// Resolve the pattern.
|
||||||
self.resolve_pattern(&*local.pat, LocalIrrefutableMode, None);
|
let mut bindings_list = HashMap::new();
|
||||||
|
self.resolve_pattern(&*local.pat,
|
||||||
|
LocalIrrefutableMode,
|
||||||
|
&mut bindings_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a map from pattern identifiers to binding-info's.
|
// build a map from pattern identifiers to binding-info's.
|
||||||
|
@ -4114,9 +4118,7 @@ impl<'a> Resolver<'a> {
|
||||||
|
|
||||||
let mut bindings_list = HashMap::new();
|
let mut bindings_list = HashMap::new();
|
||||||
for pattern in arm.pats.iter() {
|
for pattern in arm.pats.iter() {
|
||||||
self.resolve_pattern(&**pattern,
|
self.resolve_pattern(&**pattern, RefutableMode, &mut bindings_list);
|
||||||
RefutableMode,
|
|
||||||
Some(&mut bindings_list));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This has to happen *after* we determine which
|
// This has to happen *after* we determine which
|
||||||
|
@ -4262,7 +4264,7 @@ impl<'a> Resolver<'a> {
|
||||||
mode: PatternBindingMode,
|
mode: PatternBindingMode,
|
||||||
// Maps idents to the node ID for the (outermost)
|
// Maps idents to the node ID for the (outermost)
|
||||||
// pattern that binds them
|
// pattern that binds them
|
||||||
mut bindings_list: Option<&mut HashMap<Name,NodeId>>) {
|
bindings_list: &mut HashMap<Name,NodeId>) {
|
||||||
let pat_id = pattern.id;
|
let pat_id = pattern.id;
|
||||||
walk_pat(pattern, |pattern| {
|
walk_pat(pattern, |pattern| {
|
||||||
match pattern.node {
|
match pattern.node {
|
||||||
|
@ -4351,43 +4353,27 @@ impl<'a> Resolver<'a> {
|
||||||
// because that breaks the assumptions later
|
// because that breaks the assumptions later
|
||||||
// passes make about or-patterns.)
|
// passes make about or-patterns.)
|
||||||
|
|
||||||
match bindings_list {
|
if !bindings_list.contains_key(&renamed) {
|
||||||
Some(ref mut bindings_list)
|
let this = &mut *self;
|
||||||
if !bindings_list.contains_key(&renamed) => {
|
let value_ribs = this.value_ribs.borrow();
|
||||||
let this = &mut *self;
|
let length = value_ribs.len();
|
||||||
let value_ribs = this.value_ribs.borrow();
|
let last_rib = value_ribs.get(
|
||||||
let length = value_ribs.len();
|
length - 1);
|
||||||
let last_rib = value_ribs.get(
|
last_rib.bindings.borrow_mut()
|
||||||
length - 1);
|
.insert(renamed, DlDef(def));
|
||||||
last_rib.bindings.borrow_mut()
|
bindings_list.insert(renamed, pat_id);
|
||||||
.insert(renamed, DlDef(def));
|
} else if bindings_list.find(&renamed) ==
|
||||||
bindings_list.insert(renamed, pat_id);
|
Some(&pat_id) {
|
||||||
}
|
// Then this is a duplicate variable in the
|
||||||
Some(ref mut b) => {
|
// same disjunction, which is an error.
|
||||||
if b.find(&renamed) == Some(&pat_id) {
|
self.resolve_error(pattern.span,
|
||||||
// Then this is a duplicate variable
|
format!("identifier `{}` is bound \
|
||||||
// in the same disjunct, which is an
|
more than once in the same \
|
||||||
// error
|
pattern",
|
||||||
self.resolve_error(pattern.span,
|
path_to_str(path)).as_slice());
|
||||||
format!("identifier `{}` is bound \
|
|
||||||
more than once in the same \
|
|
||||||
pattern",
|
|
||||||
path_to_str(path)).as_slice());
|
|
||||||
}
|
|
||||||
// Not bound in the same pattern: do nothing
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let this = &mut *self;
|
|
||||||
{
|
|
||||||
let value_ribs = this.value_ribs.borrow();
|
|
||||||
let length = value_ribs.len();
|
|
||||||
let last_rib = value_ribs.get(
|
|
||||||
length - 1);
|
|
||||||
last_rib.bindings.borrow_mut()
|
|
||||||
.insert(renamed, DlDef(def));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Else, not bound in the same pattern: do
|
||||||
|
// nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
src/test/compile-fail/shadowing-in-the-same-pattern.rs
Normal file
18
src/test/compile-fail/shadowing-in-the-same-pattern.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Test for issue #14581.
|
||||||
|
|
||||||
|
fn f((a, a): (int, int)) {} //~ ERROR identifier `a` is bound more than once
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (a, a) = (1, 1); //~ ERROR identifier `a` is bound more than once
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue