Auto merge of #42076 - alex-ozdemir:master, r=nrc

Clearer Error Message for Duplicate Definition

Clearer use of the error message and span labels to communicate duplication definitions/imports.

fixes #42061
This commit is contained in:
bors 2017-06-21 00:06:02 +00:00
commit bb143890a4
36 changed files with 176 additions and 133 deletions

View file

@ -3450,11 +3450,11 @@ fn report_conflict(&mut self,
parent: Module,
ident: Ident,
ns: Namespace,
binding: &NameBinding,
new_binding: &NameBinding,
old_binding: &NameBinding) {
// Error on the second of two conflicting names
if old_binding.span.lo > binding.span.lo {
return self.report_conflict(parent, ident, ns, old_binding, binding);
if old_binding.span.lo > new_binding.span.lo {
return self.report_conflict(parent, ident, ns, old_binding, new_binding);
}
let container = match parent.kind {
@ -3464,12 +3464,17 @@ fn report_conflict(&mut self,
_ => "enum",
};
let (participle, noun) = match old_binding.is_import() {
true => ("imported", "import"),
false => ("defined", "definition"),
let old_noun = match old_binding.is_import() {
true => "import",
false => "definition",
};
let (name, span) = (ident.name, binding.span);
let new_participle = match new_binding.is_import() {
true => "imported",
false => "defined",
};
let (name, span) = (ident.name, new_binding.span);
if let Some(s) = self.name_already_seen.get(&name) {
if s == &span {
@ -3477,36 +3482,47 @@ fn report_conflict(&mut self,
}
}
let msg = {
let kind = match (ns, old_binding.module()) {
(ValueNS, _) => "a value",
(MacroNS, _) => "a macro",
(TypeNS, _) if old_binding.is_extern_crate() => "an extern crate",
(TypeNS, Some(module)) if module.is_normal() => "a module",
(TypeNS, Some(module)) if module.is_trait() => "a trait",
(TypeNS, _) => "a type",
};
format!("{} named `{}` has already been {} in this {}",
kind, name, participle, container)
let old_kind = match (ns, old_binding.module()) {
(ValueNS, _) => "value",
(MacroNS, _) => "macro",
(TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
(TypeNS, Some(module)) if module.is_normal() => "module",
(TypeNS, Some(module)) if module.is_trait() => "trait",
(TypeNS, _) => "type",
};
let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) {
let namespace = match ns {
ValueNS => "value",
MacroNS => "macro",
TypeNS => "type",
};
let msg = format!("the name `{}` is defined multiple times", name);
let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
(true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
(true, _) | (_, true) => match binding.is_import() && old_binding.is_import() {
(true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
true => struct_span_err!(self.session, span, E0254, "{}", msg),
false => struct_span_err!(self.session, span, E0260, "{}", msg),
},
_ => match (old_binding.is_import(), binding.is_import()) {
_ => match (old_binding.is_import(), new_binding.is_import()) {
(false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
(true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
_ => struct_span_err!(self.session, span, E0255, "{}", msg),
},
};
err.span_label(span, format!("`{}` already {}", name, participle));
err.note(&format!("`{}` must be defined only once in the {} namespace of this {}",
name,
namespace,
container));
err.span_label(span, format!("`{}` re{} here", name, new_participle));
if old_binding.span != syntax_pos::DUMMY_SP {
err.span_label(old_binding.span, format!("previous {} of `{}` here", noun, name));
err.span_label(old_binding.span, format!("previous {} of the {} `{}` here",
old_noun, old_kind, name));
}
err.emit();
self.name_already_seen.insert(name, span);
}

View file

@ -13,6 +13,6 @@
#[macro_use]
extern crate derive_a;
#[macro_use]
extern crate derive_a; //~ ERROR `derive_a` has already been imported
extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times
fn main() {}

View file

@ -11,7 +11,7 @@
#![feature(alloc)]
extern crate alloc;
//~^ NOTE previous import of `alloc` here
//~^ NOTE previous import of the extern crate `alloc` here
mod foo {
pub trait alloc {
@ -21,6 +21,7 @@ pub trait alloc {
use foo::alloc;
//~^ ERROR E0254
//~| NOTE already imported
//~| NOTE `alloc` reimported here
//~| NOTE `alloc` must be defined only once in the type namespace of this module
fn main() {}

View file

@ -11,10 +11,11 @@
#![feature(alloc, libc)]
extern crate alloc;
//~^ NOTE previous import of `alloc` here
//~^ NOTE previous import of the extern crate `alloc` here
extern crate libc as alloc;
//~^ ERROR E0259
//~| NOTE `alloc` already imported
//~| NOTE `alloc` reimported here
//~| NOTE `alloc` must be defined only once in the type namespace of this module
fn main() {}

View file

@ -11,11 +11,12 @@
#![feature(alloc)]
extern crate alloc;
//~^ NOTE previous import of `alloc` here
//~^ NOTE previous import of the extern crate `alloc` here
mod alloc {
//~^ ERROR `alloc` has already been imported in this module [E0260]
//~| NOTE `alloc` already imported
//~^ ERROR the name `alloc` is defined multiple times [E0260]
//~| NOTE `alloc` redefined here
//~| NOTE `alloc` must be defined only once in the type namespace of this module
pub trait MyTrait {
fn do_something();
}

View file

@ -8,9 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Bar; //~ previous definition of `Bar` here
struct Bar; //~ previous definition of the type `Bar` here
struct Bar; //~ ERROR E0428
//~| NOTE already defined
//~| NOTE `Bar` redefined here
//~| NOTE `Bar` must be defined only once in the type namespace of this module
fn main () {
}

View file

@ -14,6 +14,6 @@ fn main() {
{
struct Bar;
use foo::Bar;
//~^ ERROR a type named `Bar` has already been defined in this block
//~^ ERROR the name `Bar` is defined multiple times
}
}

View file

@ -8,10 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod foo { pub mod foo { } } //~ NOTE previous definition of `foo` here
mod foo { pub mod foo { } } //~ NOTE previous definition of the module `foo` here
use foo::foo;
//~^ ERROR a module named `foo` has already been defined in this module
//~| `foo` already defined
//~^ ERROR the name `foo` is defined multiple times
//~| `foo` reimported here
//~| NOTE `foo` must be defined only once in the type namespace of this module
fn main() {}

View file

@ -19,8 +19,9 @@ mod sub2 {
pub fn foo() {} // implementation 2
}
use sub1::foo; //~ NOTE previous import of `foo` here
use sub2::foo; //~ ERROR a value named `foo` has already been imported in this module [E0252]
//~| NOTE already imported
use sub1::foo; //~ NOTE previous import of the value `foo` here
use sub2::foo; //~ ERROR the name `foo` is defined multiple times
//~| NOTE `foo` reimported here
//~| NOTE `foo` must be defined only once in the value namespace of this module
fn main() {}

View file

@ -11,7 +11,7 @@
mod foo {
pub use self::bar::X;
use self::bar::X;
//~^ ERROR a type named `X` has already been imported in this module
//~^ ERROR the name `X` is defined multiple times
mod bar {
pub struct X;

View file

@ -8,12 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
enum Foo { //~ NOTE previous definition of `Foo` here
enum Foo { //~ NOTE previous definition of the type `Foo` here
X
}
mod Foo { //~ ERROR a type named `Foo` has already been defined
//~| NOTE already defined
mod Foo { //~ ERROR the name `Foo` is defined multiple times
//~| NOTE `Foo` redefined here
//~| NOTE `Foo` must be defined only once in the type namespace of this module
pub static X: isize = 42;
fn f() { f() } // Check that this does not result in a resolution error
}

View file

@ -21,9 +21,10 @@ mod c {
}
mod d {
use a::foo; //~ NOTE previous import
use a::foo; //~ ERROR `foo` has already been imported
//~| NOTE already imported
use a::foo; //~ NOTE previous import of the value `foo` here
use a::foo; //~ ERROR the name `foo` is defined multiple times
//~| NOTE `foo` reimported here
//~| NOTE `foo` must be defined only once in the value namespace of this module
}
mod e {

View file

@ -8,16 +8,19 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use self::A; //~ NOTE previous import of `A` here
use self::B; //~ NOTE previous import of `B` here
mod A {} //~ ERROR a module named `A` has already been imported in this module
//~| `A` already imported
pub mod B {} //~ ERROR a module named `B` has already been imported in this module
//~| `B` already imported
use self::A; //~ NOTE previous import of the module `A` here
use self::B; //~ NOTE previous import of the module `B` here
mod A {} //~ ERROR the name `A` is defined multiple times
//~| `A` redefined here
//~| NOTE `A` must be defined only once in the type namespace of this module
pub mod B {} //~ ERROR the name `B` is defined multiple times
//~| `B` redefined here
//~| NOTE `B` must be defined only once in the type namespace of this module
mod C {
use C::D; //~ NOTE previous import of `D` here
mod D {} //~ ERROR a module named `D` has already been imported in this module
//~| `D` already imported
use C::D; //~ NOTE previous import of the module `D` here
mod D {} //~ ERROR the name `D` is defined multiple times
//~| `D` redefined here
//~| NOTE `D` must be defined only once in the type namespace of this module
}
fn main() {}

View file

@ -12,60 +12,66 @@
#[allow(non_snake_case)]
mod Foo { }
//~^ NOTE previous definition of `Foo` here
//~^ NOTE previous definition of the module `Foo` here
#[allow(dead_code)]
struct Foo;
//~^ ERROR a module named `Foo` has already been defined in this module
//~| NOTE already defined
//~^ ERROR the name `Foo` is defined multiple times
//~| NOTE `Foo` redefined here
//~| NOTE `Foo` must be defined only once in the type namespace of this module
#[allow(non_snake_case)]
mod Bar { }
//~^ NOTE previous definition of `Bar` here
//~^ NOTE previous definition of the module `Bar` here
#[allow(dead_code)]
struct Bar(i32);
//~^ ERROR a module named `Bar` has already been defined
//~| NOTE already defined
//~^ ERROR the name `Bar` is defined multiple times
//~| NOTE `Bar` redefined here
//~| NOTE `Bar` must be defined only once in the type namespace of this module
#[allow(dead_code)]
struct Baz(i32);
//~^ NOTE previous definition
//~^ NOTE previous definition of the type `Baz` here
#[allow(non_snake_case)]
mod Baz { }
//~^ ERROR a type named `Baz` has already been defined
//~| NOTE already defined
//~^ ERROR the name `Baz` is defined multiple times
//~| NOTE `Baz` redefined here
//~| NOTE `Baz` must be defined only once in the type namespace of this module
#[allow(dead_code)]
struct Qux { x: bool }
//~^ NOTE previous definition
//~^ NOTE previous definition of the type `Qux` here
#[allow(non_snake_case)]
mod Qux { }
//~^ ERROR a type named `Qux` has already been defined
//~| NOTE already defined
//~^ ERROR the name `Qux` is defined multiple times
//~| NOTE `Qux` redefined here
//~| NOTE `Qux` must be defined only once in the type namespace of this module
#[allow(dead_code)]
struct Quux;
//~^ NOTE previous definition
//~^ NOTE previous definition of the type `Quux` here
#[allow(non_snake_case)]
mod Quux { }
//~^ ERROR a type named `Quux` has already been defined
//~| NOTE already defined
//~^ ERROR the name `Quux` is defined multiple times
//~| NOTE `Quux` redefined here
//~| NOTE `Quux` must be defined only once in the type namespace of this module
#[allow(dead_code)]
enum Corge { A, B }
//~^ NOTE previous definition
//~^ NOTE previous definition of the type `Corge` here
#[allow(non_snake_case)]
mod Corge { }
//~^ ERROR a type named `Corge` has already been defined
//~| NOTE already defined
//~^ ERROR the name `Corge` is defined multiple times
//~| NOTE `Corge` redefined here
//~| NOTE `Corge` must be defined only once in the type namespace of this module
fn main() { }

View file

@ -8,21 +8,26 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ops::Add; //~ NOTE previous import
use std::ops::Sub; //~ NOTE previous import
use std::ops::Mul; //~ NOTE previous import
use std::ops::Div; //~ NOTE previous import
use std::ops::Rem; //~ NOTE previous import
use std::ops::Add; //~ NOTE previous import of the trait `Add` here
use std::ops::Sub; //~ NOTE previous import of the trait `Sub` here
use std::ops::Mul; //~ NOTE previous import of the trait `Mul` here
use std::ops::Div; //~ NOTE previous import of the trait `Div` here
use std::ops::Rem; //~ NOTE previous import of the trait `Rem` here
type Add = bool; //~ ERROR a trait named `Add` has already been imported in this module
//~| `Add` already imported
struct Sub { x: f32 } //~ ERROR a trait named `Sub` has already been imported in this module
//~| `Sub` already imported
enum Mul { A, B } //~ ERROR a trait named `Mul` has already been imported in this module
//~| `Mul` already imported
mod Div { } //~ ERROR a trait named `Div` has already been imported in this module
//~| `Div` already imported
trait Rem { } //~ ERROR a trait named `Rem` has already been imported in this module
//~| `Rem` already imported
type Add = bool; //~ ERROR the name `Add` is defined multiple times
//~| `Add` redefined here
//~| NOTE `Add` must be defined only once in the type namespace of this module
struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times
//~| `Sub` redefined here
//~| NOTE `Sub` must be defined only once in the type namespace of this module
enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times
//~| `Mul` redefined here
//~| NOTE `Mul` must be defined only once in the type namespace of this module
mod Div { } //~ ERROR the name `Div` is defined multiple times
//~| `Div` redefined here
//~| NOTE `Div` must be defined only once in the type namespace of this module
trait Rem { } //~ ERROR the name `Rem` is defined multiple times
//~| `Rem` redefined here
//~| NOTE `Rem` must be defined only once in the type namespace of this module
fn main() {}

View file

@ -9,16 +9,16 @@
// except according to those terms.
use foo::baz;
use bar::baz; //~ ERROR a module named `baz` has already been imported
use bar::baz; //~ ERROR the name `baz` is defined multiple times
use foo::Quux;
use bar::Quux; //~ ERROR a trait named `Quux` has already been imported
use bar::Quux; //~ ERROR the name `Quux` is defined multiple times
use foo::blah;
use bar::blah; //~ ERROR a type named `blah` has already been imported
use bar::blah; //~ ERROR the name `blah` is defined multiple times
use foo::WOMP;
use bar::WOMP; //~ ERROR a value named `WOMP` has already been imported
use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times
fn main() {}

View file

@ -8,12 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::sync::{self, Arc}; //~ NOTE previous import
//~^ NOTE previous import
use std::sync::Arc; //~ ERROR a type named
//~| NOTE already imported
use std::sync; //~ ERROR a module named
//~| NOTE already imported
use std::sync::{self, Arc}; //~ NOTE previous import of the type `Arc` here
//~^ NOTE previous import of the module `sync` here
use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times
//~| NOTE `Arc` reimported here
//~| `Arc` must be defined only once in the type namespace of this module
use std::sync; //~ ERROR the name `sync` is defined multiple times
//~| NOTE `sync` reimported here
//~| `sync` must be defined only once in the type namespace of this module
fn main() {
}

View file

@ -13,10 +13,10 @@
extern {
fn foo();
pub //~ ERROR a value named `foo` has already been defined
pub //~ ERROR the name `foo` is defined multiple times
fn foo();
pub //~ ERROR a value named `foo` has already been defined
pub //~ ERROR the name `foo` is defined multiple times
static mut foo: u32;
}

View file

@ -10,6 +10,6 @@
enum a { b, c }
enum a { d, e } //~ ERROR a type named `a` has already been defined in this module
enum a { d, e } //~ ERROR the name `a` is defined multiple times
fn main() {}

View file

@ -10,6 +10,6 @@
pub mod a {}
pub mod a {} //~ ERROR a module named `a` has already been defined in this module
pub mod a {} //~ ERROR the name `a` is defined multiple times
fn main() {}

View file

@ -12,7 +12,7 @@ fn a(x: String) -> String {
format!("First function with {}", x)
}
fn a(x: String, y: String) -> String { //~ ERROR a value named `a` has already been defined
fn a(x: String, y: String) -> String { //~ ERROR the name `a` is defined multiple times
format!("Second function with {} and {}", x, y)
}

View file

@ -12,17 +12,17 @@
mod t1 {
type Foo = ::T;
mod Foo {} //~ ERROR: `Foo` has already been defined
mod Foo {} //~ ERROR the name `Foo` is defined multiple times
}
mod t2 {
type Foo = ::T;
struct Foo; //~ ERROR: `Foo` has already been defined
struct Foo; //~ ERROR the name `Foo` is defined multiple times
}
mod t3 {
type Foo = ::T;
enum Foo {} //~ ERROR: `Foo` has already been defined
enum Foo {} //~ ERROR the name `Foo` is defined multiple times
}
mod t4 {
@ -32,7 +32,7 @@ fn Foo() {} // ok
mod t5 {
type Bar<T> = T;
mod Bar {} //~ ERROR: `Bar` has already been defined
mod Bar {} //~ ERROR the name `Bar` is defined multiple times
}
mod t6 {

View file

@ -9,6 +9,6 @@
// except according to those terms.
static X: isize = 0;
struct X; //~ ERROR `X` has already been defined
struct X; //~ ERROR the name `X` is defined multiple times
fn main() {}

View file

@ -13,7 +13,7 @@
mod foo {
use baz::bar;
mod bar {}
//~^ ERROR a module named `bar` has already been imported
//~^ ERROR the name `bar` is defined multiple times
}
mod baz { pub mod bar {} }

View file

@ -10,7 +10,7 @@
#![no_std]
extern crate core; //~ ERROR: an extern crate named `core` has already
extern crate core; //~ ERROR: the name `core` is defined multiple times
extern crate std;
fn main() {}

View file

@ -9,6 +9,6 @@
// except according to those terms.
extern crate std;
//~^ ERROR an extern crate named `std` has already been imported
//~^ ERROR the name `std` is defined multiple times
fn main(){}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::slice as std; //~ ERROR an extern crate named `std` has already been imported
use std::slice as std; //~ ERROR the name `std` is defined multiple times
fn main() {
}

View file

@ -10,7 +10,7 @@
use std::mem::transmute;
use std::mem::transmute;
//~^ ERROR a value named `transmute` has already been imported
//~^ ERROR the name `transmute` is defined multiple times
fn main() {
}

View file

@ -9,7 +9,7 @@
// except according to those terms.
fn std() {}
mod std {} //~ ERROR an extern crate named `std` has already been imported
mod std {} //~ ERROR the name `std` is defined multiple times
fn main() {
}

View file

@ -9,10 +9,11 @@
// except according to those terms.
use std::mem::transmute;
//~^ NOTE previous import of `transmute` here
//~^ NOTE previous import of the value `transmute` here
fn transmute() {}
//~^ ERROR a value named `transmute` has already been imported in this module
//~| `transmute` already imported
//~^ ERROR the name `transmute` is defined multiple times
//~| `transmute` redefined here
//~| `transmute` must be defined only once in the value namespace of this module
fn main() {
}

View file

@ -11,7 +11,7 @@
use std::slice::Iter;
struct Iter;
//~^ ERROR a type named `Iter` has already been imported in this module
//~^ ERROR the name `Iter` is defined multiple times
fn main() {
}

View file

@ -9,9 +9,10 @@
// except according to those terms.
trait Foo {
fn orange(&self); //~ NOTE previous definition of `orange` here
fn orange(&self); //~ ERROR a value named `orange` has already been defined in this trait
//~| NOTE already define
fn orange(&self); //~ NOTE previous definition of the value `orange` here
fn orange(&self); //~ ERROR the name `orange` is defined multiple times
//~| NOTE `orange` redefined here
//~| NOTE `orange` must be defined only once in the value namespace of this trait
}
fn main() {}

View file

@ -10,6 +10,6 @@
extern crate core;
use core;
//~^ ERROR an extern crate named `core` has already been imported in this module
//~^ ERROR the name `core` is defined multiple times
fn main() {}

View file

@ -11,12 +11,13 @@
use foo::bar::{
self,
//~^ ERROR `self` import can only appear once in the list
//~^^ NOTE previous import of `bar` here
//~^^ NOTE previous import of the module `bar` here
Bar,
self
//~^ NOTE another `self` import appears here
//~| ERROR a module named `bar` has already been imported in this module
//~| NOTE already imported
//~| ERROR the name `bar` is defined multiple times
//~| NOTE `bar` reimported here
//~| NOTE `bar` must be defined only once in the type namespace of this module
};
use {self};

View file

@ -14,6 +14,6 @@
// Related issue: #25763
use std::{mem, ptr};
use std::mem; //~ ERROR has already been imported
use std::mem; //~ ERROR the name `mem` is defined multiple times
fn main() {}

View file

@ -32,12 +32,12 @@ enum E {
extern crate variant_namespacing;
pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
//~^ ERROR `XStruct` has already been defined
//~| ERROR `XTuple` has already been defined
//~| ERROR `XUnit` has already been defined
//~^ ERROR the name `XStruct` is defined multiple times
//~| ERROR the name `XTuple` is defined multiple times
//~| ERROR the name `XUnit` is defined multiple times
pub use E::{Struct, Tuple, Unit};
//~^ ERROR `Struct` has already been defined
//~| ERROR `Tuple` has already been defined
//~| ERROR `Unit` has already been defined
//~^ ERROR the name `Struct` is defined multiple times
//~| ERROR the name `Tuple` is defined multiple times
//~| ERROR the name `Unit` is defined multiple times
fn main() {}