Skip to content

Commit a82890e

Browse files
committed
Clearer Error Message for Duplicate Definition
Clearer use of the error message and span labels to communicate duplicaiton defitions/imports. New error format: ``` error[E0428]: the name `Foo` is defined twice --> example.rs:2:1 | 1 | trait Foo { } | ------------- previous definition of the trait `Foo` here 2 | struct Foo { } | ^^^^^^^^^^^^^^ `Foo` redefined here = note: `Foo` must be defined only once in the type namespace of this module error: aborting due to previous error ```
1 parent 258ae6d commit a82890e

36 files changed

+176
-133
lines changed

src/librustc_resolve/lib.rs

+39-23
Original file line numberDiff line numberDiff line change
@@ -3454,11 +3454,11 @@ impl<'a> Resolver<'a> {
34543454
parent: Module,
34553455
ident: Ident,
34563456
ns: Namespace,
3457-
binding: &NameBinding,
3457+
new_binding: &NameBinding,
34583458
old_binding: &NameBinding) {
34593459
// Error on the second of two conflicting names
3460-
if old_binding.span.lo > binding.span.lo {
3461-
return self.report_conflict(parent, ident, ns, old_binding, binding);
3460+
if old_binding.span.lo > new_binding.span.lo {
3461+
return self.report_conflict(parent, ident, ns, old_binding, new_binding);
34623462
}
34633463

34643464
let container = match parent.kind {
@@ -3468,49 +3468,65 @@ impl<'a> Resolver<'a> {
34683468
_ => "enum",
34693469
};
34703470

3471-
let (participle, noun) = match old_binding.is_import() {
3472-
true => ("imported", "import"),
3473-
false => ("defined", "definition"),
3471+
let old_noun = match old_binding.is_import() {
3472+
true => "import",
3473+
false => "definition",
34743474
};
34753475

3476-
let (name, span) = (ident.name, binding.span);
3476+
let new_participle = match new_binding.is_import() {
3477+
true => "imported",
3478+
false => "defined",
3479+
};
3480+
3481+
let (name, span) = (ident.name, new_binding.span);
34773482

34783483
if let Some(s) = self.name_already_seen.get(&name) {
34793484
if s == &span {
34803485
return;
34813486
}
34823487
}
34833488

3484-
let msg = {
3485-
let kind = match (ns, old_binding.module()) {
3486-
(ValueNS, _) => "a value",
3487-
(MacroNS, _) => "a macro",
3488-
(TypeNS, _) if old_binding.is_extern_crate() => "an extern crate",
3489-
(TypeNS, Some(module)) if module.is_normal() => "a module",
3490-
(TypeNS, Some(module)) if module.is_trait() => "a trait",
3491-
(TypeNS, _) => "a type",
3492-
};
3493-
format!("{} named `{}` has already been {} in this {}",
3494-
kind, name, participle, container)
3489+
let old_kind = match (ns, old_binding.module()) {
3490+
(ValueNS, _) => "value",
3491+
(MacroNS, _) => "macro",
3492+
(TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
3493+
(TypeNS, Some(module)) if module.is_normal() => "module",
3494+
(TypeNS, Some(module)) if module.is_trait() => "trait",
3495+
(TypeNS, _) => "type",
3496+
};
3497+
3498+
let namespace = match ns {
3499+
ValueNS => "value",
3500+
MacroNS => "macro",
3501+
TypeNS => "type",
34953502
};
34963503

3497-
let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) {
3504+
let msg = format!("the name `{}` is defined multiple times", name);
3505+
3506+
let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
34983507
(true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
3499-
(true, _) | (_, true) => match binding.is_import() && old_binding.is_import() {
3508+
(true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
35003509
true => struct_span_err!(self.session, span, E0254, "{}", msg),
35013510
false => struct_span_err!(self.session, span, E0260, "{}", msg),
35023511
},
3503-
_ => match (old_binding.is_import(), binding.is_import()) {
3512+
_ => match (old_binding.is_import(), new_binding.is_import()) {
35043513
(false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
35053514
(true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
35063515
_ => struct_span_err!(self.session, span, E0255, "{}", msg),
35073516
},
35083517
};
35093518

3510-
err.span_label(span, format!("`{}` already {}", name, participle));
3519+
err.note(&format!("`{}` must be defined only once in the {} namespace of this {}",
3520+
name,
3521+
namespace,
3522+
container));
3523+
3524+
err.span_label(span, format!("`{}` re{} here", name, new_participle));
35113525
if old_binding.span != syntax_pos::DUMMY_SP {
3512-
err.span_label(old_binding.span, format!("previous {} of `{}` here", noun, name));
3526+
err.span_label(old_binding.span, format!("previous {} of the {} `{}` here",
3527+
old_noun, old_kind, name));
35133528
}
3529+
35143530
err.emit();
35153531
self.name_already_seen.insert(name, span);
35163532
}

src/test/compile-fail-fulldeps/proc-macro/shadow.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
#[macro_use]
1414
extern crate derive_a;
1515
#[macro_use]
16-
extern crate derive_a; //~ ERROR `derive_a` has already been imported
16+
extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times
1717

1818
fn main() {}

src/test/compile-fail/E0254.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![feature(alloc)]
1212

1313
extern crate alloc;
14-
//~^ NOTE previous import of `alloc` here
14+
//~^ NOTE previous import of the extern crate `alloc` here
1515

1616
mod foo {
1717
pub trait alloc {
@@ -21,6 +21,7 @@ mod foo {
2121

2222
use foo::alloc;
2323
//~^ ERROR E0254
24-
//~| NOTE already imported
24+
//~| NOTE `alloc` reimported here
25+
//~| NOTE `alloc` must be defined only once in the type namespace of this module
2526

2627
fn main() {}

src/test/compile-fail/E0259.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
#![feature(alloc, libc)]
1212

1313
extern crate alloc;
14-
//~^ NOTE previous import of `alloc` here
14+
//~^ NOTE previous import of the extern crate `alloc` here
1515

1616
extern crate libc as alloc;
1717
//~^ ERROR E0259
18-
//~| NOTE `alloc` already imported
18+
//~| NOTE `alloc` reimported here
19+
//~| NOTE `alloc` must be defined only once in the type namespace of this module
1920

2021
fn main() {}

src/test/compile-fail/E0260.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
#![feature(alloc)]
1212

1313
extern crate alloc;
14-
//~^ NOTE previous import of `alloc` here
14+
//~^ NOTE previous import of the extern crate `alloc` here
1515

1616
mod alloc {
17-
//~^ ERROR `alloc` has already been imported in this module [E0260]
18-
//~| NOTE `alloc` already imported
17+
//~^ ERROR the name `alloc` is defined multiple times [E0260]
18+
//~| NOTE `alloc` redefined here
19+
//~| NOTE `alloc` must be defined only once in the type namespace of this module
1920
pub trait MyTrait {
2021
fn do_something();
2122
}

src/test/compile-fail/E0428.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
struct Bar; //~ previous definition of `Bar` here
11+
struct Bar; //~ previous definition of the type `Bar` here
1212
struct Bar; //~ ERROR E0428
13-
//~| NOTE already defined
13+
//~| NOTE `Bar` redefined here
14+
//~| NOTE `Bar` must be defined only once in the type namespace of this module
1415

1516
fn main () {
1617
}

src/test/compile-fail/blind-item-block-item-shadow.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ fn main() {
1414
{
1515
struct Bar;
1616
use foo::Bar;
17-
//~^ ERROR a type named `Bar` has already been defined in this block
17+
//~^ ERROR the name `Bar` is defined multiple times
1818
}
1919
}

src/test/compile-fail/blind-item-item-shadow.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
mod foo { pub mod foo { } } //~ NOTE previous definition of `foo` here
11+
mod foo { pub mod foo { } } //~ NOTE previous definition of the module `foo` here
1212

1313
use foo::foo;
14-
//~^ ERROR a module named `foo` has already been defined in this module
15-
//~| `foo` already defined
14+
//~^ ERROR the name `foo` is defined multiple times
15+
//~| `foo` reimported here
16+
//~| NOTE `foo` must be defined only once in the type namespace of this module
1617

1718
fn main() {}

src/test/compile-fail/double-import.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ mod sub2 {
1919
pub fn foo() {} // implementation 2
2020
}
2121

22-
use sub1::foo; //~ NOTE previous import of `foo` here
23-
use sub2::foo; //~ ERROR a value named `foo` has already been imported in this module [E0252]
24-
//~| NOTE already imported
22+
use sub1::foo; //~ NOTE previous import of the value `foo` here
23+
use sub2::foo; //~ ERROR the name `foo` is defined multiple times
24+
//~| NOTE `foo` reimported here
25+
//~| NOTE `foo` must be defined only once in the value namespace of this module
2526

2627
fn main() {}

src/test/compile-fail/double-type-import.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
mod foo {
1212
pub use self::bar::X;
1313
use self::bar::X;
14-
//~^ ERROR a type named `X` has already been imported in this module
14+
//~^ ERROR the name `X` is defined multiple times
1515

1616
mod bar {
1717
pub struct X;

src/test/compile-fail/enum-and-module-in-same-scope.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
enum Foo { //~ NOTE previous definition of `Foo` here
11+
enum Foo { //~ NOTE previous definition of the type `Foo` here
1212
X
1313
}
1414

15-
mod Foo { //~ ERROR a type named `Foo` has already been defined
16-
//~| NOTE already defined
15+
mod Foo { //~ ERROR the name `Foo` is defined multiple times
16+
//~| NOTE `Foo` redefined here
17+
//~| NOTE `Foo` must be defined only once in the type namespace of this module
1718
pub static X: isize = 42;
1819
fn f() { f() } // Check that this does not result in a resolution error
1920
}

src/test/compile-fail/imports/duplicate.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ mod c {
2121
}
2222

2323
mod d {
24-
use a::foo; //~ NOTE previous import
25-
use a::foo; //~ ERROR `foo` has already been imported
26-
//~| NOTE already imported
24+
use a::foo; //~ NOTE previous import of the value `foo` here
25+
use a::foo; //~ ERROR the name `foo` is defined multiple times
26+
//~| NOTE `foo` reimported here
27+
//~| NOTE `foo` must be defined only once in the value namespace of this module
2728
}
2829

2930
mod e {

src/test/compile-fail/issue-19498.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,19 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use self::A; //~ NOTE previous import of `A` here
12-
use self::B; //~ NOTE previous import of `B` here
13-
mod A {} //~ ERROR a module named `A` has already been imported in this module
14-
//~| `A` already imported
15-
pub mod B {} //~ ERROR a module named `B` has already been imported in this module
16-
//~| `B` already imported
11+
use self::A; //~ NOTE previous import of the module `A` here
12+
use self::B; //~ NOTE previous import of the module `B` here
13+
mod A {} //~ ERROR the name `A` is defined multiple times
14+
//~| `A` redefined here
15+
//~| NOTE `A` must be defined only once in the type namespace of this module
16+
pub mod B {} //~ ERROR the name `B` is defined multiple times
17+
//~| `B` redefined here
18+
//~| NOTE `B` must be defined only once in the type namespace of this module
1719
mod C {
18-
use C::D; //~ NOTE previous import of `D` here
19-
mod D {} //~ ERROR a module named `D` has already been imported in this module
20-
//~| `D` already imported
20+
use C::D; //~ NOTE previous import of the module `D` here
21+
mod D {} //~ ERROR the name `D` is defined multiple times
22+
//~| `D` redefined here
23+
//~| NOTE `D` must be defined only once in the type namespace of this module
2124
}
2225

2326
fn main() {}

src/test/compile-fail/issue-21546.rs

+24-18
Original file line numberDiff line numberDiff line change
@@ -12,60 +12,66 @@
1212

1313
#[allow(non_snake_case)]
1414
mod Foo { }
15-
//~^ NOTE previous definition of `Foo` here
15+
//~^ NOTE previous definition of the module `Foo` here
1616

1717
#[allow(dead_code)]
1818
struct Foo;
19-
//~^ ERROR a module named `Foo` has already been defined in this module
20-
//~| NOTE already defined
19+
//~^ ERROR the name `Foo` is defined multiple times
20+
//~| NOTE `Foo` redefined here
21+
//~| NOTE `Foo` must be defined only once in the type namespace of this module
2122

2223
#[allow(non_snake_case)]
2324
mod Bar { }
24-
//~^ NOTE previous definition of `Bar` here
25+
//~^ NOTE previous definition of the module `Bar` here
2526

2627
#[allow(dead_code)]
2728
struct Bar(i32);
28-
//~^ ERROR a module named `Bar` has already been defined
29-
//~| NOTE already defined
29+
//~^ ERROR the name `Bar` is defined multiple times
30+
//~| NOTE `Bar` redefined here
31+
//~| NOTE `Bar` must be defined only once in the type namespace of this module
3032

3133

3234
#[allow(dead_code)]
3335
struct Baz(i32);
34-
//~^ NOTE previous definition
36+
//~^ NOTE previous definition of the type `Baz` here
3537

3638
#[allow(non_snake_case)]
3739
mod Baz { }
38-
//~^ ERROR a type named `Baz` has already been defined
39-
//~| NOTE already defined
40+
//~^ ERROR the name `Baz` is defined multiple times
41+
//~| NOTE `Baz` redefined here
42+
//~| NOTE `Baz` must be defined only once in the type namespace of this module
4043

4144

4245
#[allow(dead_code)]
4346
struct Qux { x: bool }
44-
//~^ NOTE previous definition
47+
//~^ NOTE previous definition of the type `Qux` here
4548

4649
#[allow(non_snake_case)]
4750
mod Qux { }
48-
//~^ ERROR a type named `Qux` has already been defined
49-
//~| NOTE already defined
51+
//~^ ERROR the name `Qux` is defined multiple times
52+
//~| NOTE `Qux` redefined here
53+
//~| NOTE `Qux` must be defined only once in the type namespace of this module
5054

5155

5256
#[allow(dead_code)]
5357
struct Quux;
54-
//~^ NOTE previous definition
58+
//~^ NOTE previous definition of the type `Quux` here
5559

5660
#[allow(non_snake_case)]
5761
mod Quux { }
58-
//~^ ERROR a type named `Quux` has already been defined
59-
//~| NOTE already defined
62+
//~^ ERROR the name `Quux` is defined multiple times
63+
//~| NOTE `Quux` redefined here
64+
//~| NOTE `Quux` must be defined only once in the type namespace of this module
6065

6166

6267
#[allow(dead_code)]
6368
enum Corge { A, B }
64-
//~^ NOTE previous definition
69+
//~^ NOTE previous definition of the type `Corge` here
6570

6671
#[allow(non_snake_case)]
6772
mod Corge { }
68-
//~^ ERROR a type named `Corge` has already been defined
69-
//~| NOTE already defined
73+
//~^ ERROR the name `Corge` is defined multiple times
74+
//~| NOTE `Corge` redefined here
75+
//~| NOTE `Corge` must be defined only once in the type namespace of this module
7076

7177
fn main() { }

0 commit comments

Comments
 (0)