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

nham
Copy link
Contributor

@nham nham commented Jun 19, 2015

Fixes #21546.

@rust-highfive
Copy link
Collaborator

r? @pcwalton

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

@alexcrichton
Copy link
Member

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
Copy link
Contributor

brson commented Jun 19, 2015

I've started this on crater.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@pnkfelix
Copy link
Member

@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
Copy link
Member

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
Copy link
Member

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
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
Copy link
Contributor

brson commented Jun 24, 2015

@alexcrichton alexcrichton added I-needs-decision Issue: In need of a decision. T-lang Relevant to the language team, which will review and decide on the PR/issue. I-nominated and removed I-needs-decision Issue: In need of a decision. labels Jun 25, 2015
@alexcrichton
Copy link
Member

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

@pnkfelix
Copy link
Member

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
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
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
Copy link
Contributor

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
Copy link
Member

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

@bors
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
Copy link
Member

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
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
Copy link
Member

@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. :)

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

@WildCryptoFox
Copy link
Contributor

@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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@pnkfelix
Copy link
Member

@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
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Oct 27, 2015

📌 Commit f0af1eb has been approved by pnkfelix

@bors
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants