Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not allow a module and tuple struct of the same name to coexist. #26421

Merged
merged 1 commit into from Oct 27, 2015

Conversation

Projects
None yet
10 participants
@nham
Copy link
Contributor

nham commented Jun 19, 2015

Fixes #21546.

@rust-highfive

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Jun 19, 2015

r? @pcwalton

(rust_highfive has picked a reviewer for you, use r? to override)

@nham nham force-pushed the nham:fix_21546 branch from a8cfb62 to d6c0753 Jun 19, 2015

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jun 19, 2015

This is unfortunately a breaking change, so we need to be sure to tread carefully here (especially in resolve).

cc @rust-lang/lang, @nrc, I forget if cases like this were intentional or not?
cc @brson, perhaps a crater run to see if this causes compiles to fail?

@brson

This comment has been minimized.

Copy link
Contributor

brson commented Jun 19, 2015

I've started this on crater.

struct Foo;
//~^ ERROR duplicate definition of type or module `Foo`

This comment has been minimized.

@pnkfelix

pnkfelix Jun 20, 2015

Member

given that [RFC 218]("empty struct with braces") was accepted, it would probably be a good idea to have both this test and a separate one of non-empty tuple structs, since I expect the code paths for how the two are handled to diverge somewhat in the future.

This comment has been minimized.

@nham

nham Jun 20, 2015

Author Contributor

done

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Jun 20, 2015

@alexcrichton asked:

cc @rust-lang/lang, @nrc, I forget if cases like this were intentional or not?

I'm pretty sure this was an oversight. Every kind of struct definition puts an entry into the type namespace (while only some put an entry into the value namespace, but this is not relevant). The collision at the type namespace level is what is problematic.

In other words, this errors today:

mod Foo {}
struct Foo { x: i32 }

fn main() {}

so there's no reason for these to be succeeding:

mod Foo {}
struct Foo(i32);

fn main() {}

and

mod Foo {}
struct Foo;

fn main() {}
@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Jun 20, 2015

Here is a more concrete example of a problematic program this bug is exposing:

#[allow(non_snake_case)]
mod Foo { pub fn foo() -> i32 { 4 } }

struct Foo(i32);
impl Foo { fn foo() -> i32 { 3 } }

fn main() { println!("foo: {}", Foo::foo()); } // what does this print?
@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Jun 20, 2015

Having said that, its not a soundness issue to my knowledge.

Fixing it would not break code that is following "usual" style conventions about struct and module names, but otherwise it is indeed a breaking change.

Does it qualify as a course correction, or just a bug fix? We could certainly employ the #[legacy(...)] flag idea here, I would imagine, but is it called for here, is my question. See also the recently accepted RFC 1122.

@nrc

This comment has been minimized.

Copy link
Member

nrc commented Jun 23, 2015

This was not intentional. I think it is definitely a bug fix, not a course correction or 'proper' breaking change.

@brson

This comment has been minimized.

Copy link
Contributor

brson commented Jun 24, 2015

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jun 25, 2015

Tagging with T-lang and I-nominated, just getting some broader visibility (and will be dealt with during triage)

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Jul 20, 2015

Similarly to #27026 (which was specifically mentioned during the last lang team meeting, where the response was "warning cycle first, then release the breaking change"), I am again wondering whether this needs to go through a warning cycle or not.

I interpret @nrc above as saying "no, it does not need a warning cycle." But if that is the case, then why apply a different policy to #27026 ? Are these two cases all that different?

cc @rust-lang/lang

@nrc

This comment has been minimized.

Copy link
Member

nrc commented Jul 20, 2015

I think it could (and probably should) get a warning cycle. I don't think it should get a legacy flag or anything more permanent than a warning cycle.

@nham

This comment has been minimized.

Copy link
Contributor Author

nham commented Jul 20, 2015

So under this policy, does the change in #25993 need to be reverted and have a warning cycle added? The following program used to compile pre-patch, but does not after:

trait Foo {
    type Ty;
}

impl Foo for () {
    type Ty = ();
    type Ty = usize;
}

fn main() { 
    let _: <() as Foo>::Ty = ();
}
@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jul 23, 2015

Triage: removing I-nominated as we've taken a look. Seems like a warning cycle makes sense, given how widely used tuple structs and modules are. With respect to #25993, I think we can let that go --- istm that overlap there is less likely, and of course we'll see if crater picks up anything.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Sep 28, 2015

ping? @nham would you be ok implementing a warning for this change?

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Oct 14, 2015

☔️ The latest upstream changes (presumably #28816) made this pull request unmergeable. Please resolve the merge conflicts.

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Oct 18, 2015

Re assigning to myself, I will try to revise with warning cycle support if we see no response from @nham

@pnkfelix pnkfelix assigned pnkfelix and unassigned pcwalton Oct 18, 2015

@nham

This comment has been minimized.

Copy link
Contributor Author

nham commented Oct 18, 2015

Sorry, I've been busy the past couple of weeks. I have some time to look at it this week, but I still need to figure out how the warning cycles work, so if you want to take it @pnkfelix that's okay with me.

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Oct 18, 2015

@nham oh I have plenty of other stuff on my plate, so you've got time to look at it this week if you like. :)

Nick Hamann
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.

@nham nham force-pushed the nham:fix_21546 branch from da2d1fa to f0af1eb Oct 22, 2015

@nham

This comment has been minimized.

Copy link
Contributor Author

nham commented Oct 22, 2015

I've made an attempt at adding warnings. The warnings address both the original issue and another issue mentioned by @james-darkfox in #29185, which is that programs like this currently compile:

struct Foo { x: i32 }
mod Foo { }
fn main() {}

This is slightly different from the original issue because it is allowed only when the module comes after the struct, and also because it works for all structs, not just unit/tuple structs.

I wasn't sure what to put for the warning message. Looking for feedback here!

@james-darkfox

This comment has been minimized.

Copy link
Contributor

james-darkfox commented Oct 23, 2015

@nham Sidenote: I'm "abusing" this bug in #29182 due to a limitation in the test cases. Here in the module I have my #[test] fn .... My point here is that although this is a bug, it is a useful one until the #[test] cases can be implemented in impl blocks.

@@ -404,6 +404,29 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}

ItemMod(..) => {
let child = parent.children.borrow().get(&name).cloned();

This comment has been minimized.

@pnkfelix

pnkfelix Oct 27, 2015

Member

Seems a shame to clone the child; I would have thought there was a way to structure this to avoid that.

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!(

This comment has been minimized.

@pnkfelix

pnkfelix Oct 27, 2015

Member

should we consider allocating a error number now for this?

I guess it can wait until we promote the warning into a proper error, since I don't know if our error number policy would allow us to reuse the same number for the warning and the error it is later promoted into.

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Oct 27, 2015

@nham this looks fine to me, apart from the clone, which I assume you tried to avoid and I must just be missing some reason why you found it necessary

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Oct 27, 2015

@bors r+

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Oct 27, 2015

📌 Commit f0af1eb has been approved by pnkfelix

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Oct 27, 2015

⌛️ Testing commit f0af1eb with merge a1e2a55...

bors added a commit that referenced this pull request Oct 27, 2015

@bors bors merged commit f0af1eb into rust-lang:master Oct 27, 2015

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.