librustc: Forbid duplicate name bindings in the same parameter or type
parameter list. This breaks code like: fn f(a: int, a: int) { ... } fn g<T,T>(a: T) { ... } Change this code to not use the same name for a parameter. For example: fn f(a: int, b: int) { ... } fn g<T,U>(a: T) { ... } Code like this is *not* affected, since `_` is not an identifier: fn f(_: int, _: int) { ... } // OK Closes #17568. [breaking-change]
This commit is contained in:
parent
63fe80e1ff
commit
1498814195
3 changed files with 83 additions and 6 deletions
|
@ -4232,15 +4232,25 @@ impl<'a> Resolver<'a> {
|
||||||
type_parameters: TypeParameters,
|
type_parameters: TypeParameters,
|
||||||
f: |&mut Resolver|) {
|
f: |&mut Resolver|) {
|
||||||
match type_parameters {
|
match type_parameters {
|
||||||
HasTypeParameters(generics, space, node_id,
|
HasTypeParameters(generics, space, node_id, rib_kind) => {
|
||||||
rib_kind) => {
|
|
||||||
|
|
||||||
let mut function_type_rib = Rib::new(rib_kind);
|
let mut function_type_rib = Rib::new(rib_kind);
|
||||||
|
let mut seen_bindings = HashSet::new();
|
||||||
for (index, type_parameter) in generics.ty_params.iter().enumerate() {
|
for (index, type_parameter) in generics.ty_params.iter().enumerate() {
|
||||||
let ident = type_parameter.ident;
|
let ident = type_parameter.ident;
|
||||||
debug!("with_type_parameter_rib: {} {}", node_id,
|
debug!("with_type_parameter_rib: {} {}", node_id,
|
||||||
type_parameter.id);
|
type_parameter.id);
|
||||||
|
|
||||||
|
if seen_bindings.contains(&ident) {
|
||||||
|
self.resolve_error(type_parameter.span,
|
||||||
|
format!("the name `{}` is already \
|
||||||
|
used for a type \
|
||||||
|
parameter in this type \
|
||||||
|
parameter list",
|
||||||
|
token::get_ident(
|
||||||
|
ident)).as_slice())
|
||||||
|
}
|
||||||
|
seen_bindings.insert(ident);
|
||||||
|
|
||||||
let def_like = DlDef(DefTyParam(space,
|
let def_like = DlDef(DefTyParam(space,
|
||||||
local_def(type_parameter.id),
|
local_def(type_parameter.id),
|
||||||
index));
|
index));
|
||||||
|
@ -4313,8 +4323,8 @@ impl<'a> Resolver<'a> {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
Some(declaration) => {
|
Some(declaration) => {
|
||||||
|
let mut bindings_list = HashMap::new();
|
||||||
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,
|
||||||
&mut bindings_list);
|
&mut bindings_list);
|
||||||
|
@ -5056,12 +5066,24 @@ impl<'a> Resolver<'a> {
|
||||||
// must not add it if it's in the bindings list
|
// must not add it if it's in the bindings list
|
||||||
// because that breaks the assumptions later
|
// because that breaks the assumptions later
|
||||||
// passes make about or-patterns.)
|
// passes make about or-patterns.)
|
||||||
|
|
||||||
if !bindings_list.contains_key(&renamed) {
|
if !bindings_list.contains_key(&renamed) {
|
||||||
let this = &mut *self;
|
let this = &mut *self;
|
||||||
let last_rib = this.value_ribs.last_mut().unwrap();
|
let last_rib = this.value_ribs.last_mut().unwrap();
|
||||||
last_rib.bindings.insert(renamed, DlDef(def));
|
last_rib.bindings.insert(renamed, DlDef(def));
|
||||||
bindings_list.insert(renamed, pat_id);
|
bindings_list.insert(renamed, pat_id);
|
||||||
|
} else if mode == ArgumentIrrefutableMode &&
|
||||||
|
bindings_list.contains_key(&renamed) {
|
||||||
|
// Forbid duplicate bindings in the same
|
||||||
|
// parameter list.
|
||||||
|
self.resolve_error(pattern.span,
|
||||||
|
format!("identifier `{}` \
|
||||||
|
is bound more \
|
||||||
|
than once in \
|
||||||
|
this parameter \
|
||||||
|
list",
|
||||||
|
token::get_ident(
|
||||||
|
ident))
|
||||||
|
.as_slice())
|
||||||
} else if bindings_list.find(&renamed) ==
|
} else if bindings_list.find(&renamed) ==
|
||||||
Some(&pat_id) {
|
Some(&pat_id) {
|
||||||
// Then this is a duplicate variable in the
|
// Then this is a duplicate variable in the
|
||||||
|
|
16
src/test/compile-fail/duplicate-parameter.rs
Normal file
16
src/test/compile-fail/duplicate-parameter.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
fn f(a: int, a: int) {}
|
||||||
|
//~^ ERROR identifier `a` is bound more than once in this parameter list
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
||||||
|
|
39
src/test/compile-fail/duplicate-type-parameter.rs
Normal file
39
src/test/compile-fail/duplicate-type-parameter.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
type Foo<T,T> = Option<T>;
|
||||||
|
//~^ ERROR the name `T` is already used
|
||||||
|
|
||||||
|
struct Bar<T,T>(T);
|
||||||
|
//~^ ERROR the name `T` is already used
|
||||||
|
|
||||||
|
struct Baz<T,T> {
|
||||||
|
//~^ ERROR the name `T` is already used
|
||||||
|
x: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Boo<T,T> {
|
||||||
|
//~^ ERROR the name `T` is already used
|
||||||
|
A(T),
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quux<T,T>(x: T) {}
|
||||||
|
//~^ ERROR the name `T` is already used
|
||||||
|
|
||||||
|
trait Qux<T,T> {}
|
||||||
|
//~^ ERROR the name `T` is already used
|
||||||
|
|
||||||
|
impl<T,T> Qux<T,T> for Option<T> {}
|
||||||
|
//~^ ERROR the name `T` is already used
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue