Skip to content

Commit 1498814

Browse files
committed
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]
1 parent 63fe80e commit 1498814

File tree

3 files changed

+83
-6
lines changed

3 files changed

+83
-6
lines changed

src/librustc/middle/resolve.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -4232,15 +4232,25 @@ impl<'a> Resolver<'a> {
42324232
type_parameters: TypeParameters,
42334233
f: |&mut Resolver|) {
42344234
match type_parameters {
4235-
HasTypeParameters(generics, space, node_id,
4236-
rib_kind) => {
4237-
4235+
HasTypeParameters(generics, space, node_id, rib_kind) => {
42384236
let mut function_type_rib = Rib::new(rib_kind);
4239-
4237+
let mut seen_bindings = HashSet::new();
42404238
for (index, type_parameter) in generics.ty_params.iter().enumerate() {
42414239
let ident = type_parameter.ident;
42424240
debug!("with_type_parameter_rib: {} {}", node_id,
42434241
type_parameter.id);
4242+
4243+
if seen_bindings.contains(&ident) {
4244+
self.resolve_error(type_parameter.span,
4245+
format!("the name `{}` is already \
4246+
used for a type \
4247+
parameter in this type \
4248+
parameter list",
4249+
token::get_ident(
4250+
ident)).as_slice())
4251+
}
4252+
seen_bindings.insert(ident);
4253+
42444254
let def_like = DlDef(DefTyParam(space,
42454255
local_def(type_parameter.id),
42464256
index));
@@ -4313,8 +4323,8 @@ impl<'a> Resolver<'a> {
43134323
// Nothing to do.
43144324
}
43154325
Some(declaration) => {
4326+
let mut bindings_list = HashMap::new();
43164327
for argument in declaration.inputs.iter() {
4317-
let mut bindings_list = HashMap::new();
43184328
this.resolve_pattern(&*argument.pat,
43194329
ArgumentIrrefutableMode,
43204330
&mut bindings_list);
@@ -5056,12 +5066,24 @@ impl<'a> Resolver<'a> {
50565066
// must not add it if it's in the bindings list
50575067
// because that breaks the assumptions later
50585068
// passes make about or-patterns.)
5059-
50605069
if !bindings_list.contains_key(&renamed) {
50615070
let this = &mut *self;
50625071
let last_rib = this.value_ribs.last_mut().unwrap();
50635072
last_rib.bindings.insert(renamed, DlDef(def));
50645073
bindings_list.insert(renamed, pat_id);
5074+
} else if mode == ArgumentIrrefutableMode &&
5075+
bindings_list.contains_key(&renamed) {
5076+
// Forbid duplicate bindings in the same
5077+
// parameter list.
5078+
self.resolve_error(pattern.span,
5079+
format!("identifier `{}` \
5080+
is bound more \
5081+
than once in \
5082+
this parameter \
5083+
list",
5084+
token::get_ident(
5085+
ident))
5086+
.as_slice())
50655087
} else if bindings_list.find(&renamed) ==
50665088
Some(&pat_id) {
50675089
// Then this is a duplicate variable in the
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn f(a: int, a: int) {}
12+
//~^ ERROR identifier `a` is bound more than once in this parameter list
13+
14+
fn main() {
15+
}
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
type Foo<T,T> = Option<T>;
12+
//~^ ERROR the name `T` is already used
13+
14+
struct Bar<T,T>(T);
15+
//~^ ERROR the name `T` is already used
16+
17+
struct Baz<T,T> {
18+
//~^ ERROR the name `T` is already used
19+
x: T,
20+
}
21+
22+
enum Boo<T,T> {
23+
//~^ ERROR the name `T` is already used
24+
A(T),
25+
B,
26+
}
27+
28+
fn quux<T,T>(x: T) {}
29+
//~^ ERROR the name `T` is already used
30+
31+
trait Qux<T,T> {}
32+
//~^ ERROR the name `T` is already used
33+
34+
impl<T,T> Qux<T,T> for Option<T> {}
35+
//~^ ERROR the name `T` is already used
36+
37+
fn main() {
38+
}
39+

0 commit comments

Comments
 (0)