From f0af1eb110b3dd12754b02bc3dcb7127ea2dce7f Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Thu, 22 Oct 2015 14:53:01 -0500 Subject: [PATCH] Warn when creating a module and a struct that both have the same name. Currently it is possible to do the following: - define a module named `Foo` and then a unit or tuple struct also named `Foo` - define any struct named `Foo` and then a module named `Foo` This commit introduces a warning for both of these cases. --- src/librustc_resolve/build_reduced_graph.rs | 45 ++++++++++++++ src/test/compile-fail/issue-21546.rs | 65 +++++++++++++++++++++ src/test/run-pass/issue-14564.rs | 15 ----- 3 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 src/test/compile-fail/issue-21546.rs delete mode 100644 src/test/run-pass/issue-14564.rs diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index c051f8c263723..52ec3a0dbf926 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -404,6 +404,29 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } ItemMod(..) => { + let child = parent.children.borrow().get(&name).cloned(); + if let Some(child) = child { + // check if there's struct of the same name already defined + if child.defined_in_namespace(TypeNS) + && child.get_module_if_available().is_none() { + self.session.span_warn(sp, &format!( + "duplicate definition of {} `{}`. \ + Defining a module and a struct with \ + the same name will be disallowed \ + soon.", + namespace_error_to_string(TypeError), + name)); + { + let r = child.span_for_namespace(TypeNS); + if let Some(sp) = r { + self.session.span_note(sp, + &format!("first definition of {} `{}` here", + namespace_error_to_string(TypeError), + name)); + } + } + } + } let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp); let parent_link = self.get_parent_link(parent, name); @@ -495,6 +518,28 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let (forbid, ctor_id) = if struct_def.is_struct() { (ForbidDuplicateTypesAndModules, None) } else { + let child = parent.children.borrow().get(&name).cloned(); + if let Some(child) = child { + // check if theres a DefMod + if let Some(DefMod(_)) = child.def_for_namespace(TypeNS) { + self.session.span_warn(sp, &format!( + "duplicate definition of {} `{}`. \ + Defining a module and a struct with \ + the same name will be disallowed \ + soon.", + namespace_error_to_string(TypeError), + name)); + { + let r = child.span_for_namespace(TypeNS); + if let Some(sp) = r { + self.session.span_note(sp, + &format!("first definition of {} `{}` here", + namespace_error_to_string(TypeError), + name)); + } + } + } + } (ForbidDuplicateTypesAndValues, Some(struct_def.id())) }; diff --git a/src/test/compile-fail/issue-21546.rs b/src/test/compile-fail/issue-21546.rs new file mode 100644 index 0000000000000..bb1bcd4e8717d --- /dev/null +++ b/src/test/compile-fail/issue-21546.rs @@ -0,0 +1,65 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Also works as a test for #14564 + +#[allow(non_snake_case)] +mod Foo { } +//~^ NOTE first definition of type or module `Foo` + +#[allow(dead_code)] +struct Foo; +//~^ WARNING duplicate definition of type or module `Foo` + + +#[allow(non_snake_case)] +mod Bar { } +//~^ NOTE first definition of type or module `Bar` + +#[allow(dead_code)] +struct Bar(i32); +//~^ WARNING duplicate definition of type or module `Bar` + + +#[allow(dead_code)] +struct Baz(i32); +//~^ NOTE first definition of type or module + +#[allow(non_snake_case)] +mod Baz { } +//~^ WARNING duplicate definition of type or module `Baz` + + +#[allow(dead_code)] +struct Qux { x: bool } +//~^ NOTE first definition of type or module + +#[allow(non_snake_case)] +mod Qux { } +//~^ WARNING duplicate definition of type or module `Qux` + + +#[allow(dead_code)] +struct Quux; +//~^ NOTE first definition of type or module + +#[allow(non_snake_case)] +mod Quux { } +//~^ WARNING duplicate definition of type or module `Quux` + + +#[allow(dead_code)] +enum Corge { A, B } + +#[allow(non_snake_case)] +mod Corge { } +//~^ ERROR duplicate definition of type or module `Corge` + +fn main() { } diff --git a/src/test/run-pass/issue-14564.rs b/src/test/run-pass/issue-14564.rs deleted file mode 100644 index a661437a44ccf..0000000000000 --- a/src/test/run-pass/issue-14564.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod Foo { } -struct Foo; -impl Foo { } - -fn main() { }