-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Closed
Labels
T-langRelevant to the language teamRelevant to the language team
Description
For example,
mod foo {
mod bar {
pub fn f() { println!("foo"); }
}
pub use self::bar::f;
}
pub use foo::*;
pub fn f() { println!("baz"); }
fn main() {
f(); // Prints "baz"
}
Also, considering the above example as a crate, the glob import used to shadow the item from the perspective of users of the crate before #30843. After #30843, the item shadows the glob import both inside and outside the crate. I can easily revert that breaking change if desired (crater found no breakage in practice).
Finally, in the generated documentation for the crate, f
is listed twice, both times as the glob imported version, i.e. the glob import still shadows the item in the crate documentation.
Metadata
Metadata
Assignees
Labels
T-langRelevant to the language teamRelevant to the language team
Activity
[-]Items can be shadowed by glob-imported reexports[/-][+]Items shadow glob-imported reexports[/+]Aatch commentedon Feb 1, 2016
Seems like an unfinished sentence?
try_define
#31308jseyfried commentedon Feb 1, 2016
I think there are two reasonable ways to fix this:
jseyfried commentedon Feb 1, 2016
cc @nrc @nikomatsakis
retep998 commentedon Feb 1, 2016
I think it was intentional for non-glob items (whether declared there or via imports) to be able to override glob imports and I'd rather keep it that way.
nrc commentedon Feb 1, 2016
My opinion here is that we should allow local items to shadow glob imported items, otherwise adding an item to the upstream module can break the downstream one, and it is fairly clear that local declarations should have priority (I'm less sure about glob and non-glob imports, I like the idea that we can have multiple imports if they import the same item or the import is not used, but re-exports must count as 'used', so I'm not sure there).
Anyway, this is basically arguing for option 2 - fix the docs.
jseyfried commentedon Feb 1, 2016
@nrc Ok, I agree that glob imported items should be shadowable.
Do you think we should allow only one namespace of a name that is defined in both namespaces by a single item to be shadowed? For example,
When generating the documentation for this example, would we list the struct Bar and the function Bar? That seems like it would cause confusion, since the constructor for the struct is not in fact exported.
We could instead not list the struct at all and disallow use of the type Bar from outside of the crate but continue allowing it within the crate.
Finally, we could disallow use of the type Bar inside and outside the crate, i.e. we could have the function shadow the struct in both namespaces, effectively "undefining" Bar in the type namespace.
nrc commentedon Feb 1, 2016
I think that we should at least lint against this, if not forbid it out right (i.e., make it an error to shadow one namespace but not the other, when the items in the same namespace are 'linked'). This means making a connection between the two
Bar
names in different namespaces, which is unfortunate, but I think the least confusing path for the user. If we lint instead of error, then I think we should adopt the semantics from your last option.petrochenkov commentedon Feb 1, 2016
This is unfortunate.
Glob shadowing should either be properly (not accidentally and only in some cases) implemented or prohibited.
The former is certainly the way to go in the long term, probably with an RFC describing the design in detail (for all cases including glob vs glob, glob vs prelude etc.).
The latter is a better immediate solution, I think (with a crater run, of course), unless @jseyfried has a working implementation for the former :)
nikomatsakis commentedon Feb 1, 2016
I think we should revert the change, even though I prefer the shadowing semantics in the long term. Basically, I think we ought to do an RFC that describes this change, in addition to incorporating the more general work we've been planning on macro and name resolution.
nikomatsakis commentedon Feb 1, 2016
Also, the question of multiple namespaces is an important one. I think it came up in the revised name resolution algorithm I was planning -- though I didn't extend my latest prototype to cover multiple paths, so maybe I am remembering details from an older version. But I remember thinking that there are some somewhat subtle interactions arising there.
Ah, I sort of remember now. The problem was I think specific to my older, monotonic variants, where we had to know whether
use foo::bar::f;
should shadow a module that came in via glob, and we couldn't necessarily know that until we resolvedfoo::bar
fully (which might itself depend on the glob). I think it's less of an issue with the newer, "eager" variants.(Sorry, these comments are kind of rambly, but for context, I am discussing the algorithm here https://github.com/nikomatsakis/rust-name-resolution-algorithm.)
petrochenkov commentedon Feb 2, 2016
@nrc
I'd prefer non-glob imports to behave exactly like other items, i.e. they cannot have name conflicts, are visible from other modules even when private, can shadow glob imports etc. This give us one simple scheme which is easy to teach and contains no surprises. (Yes, it could be useful sometimes to import the same thing twice in macros, but it's not a great loss IMO, we don't have it now and I haven't seem complaints so far.)
All the shadowing rules and complexities will be concentrated around globs and prelude then.
But I'm digressing, this would be better discussed in the RFC.
14 remaining items
nikomatsakis commentedon Feb 12, 2016
We discussed this in the @rust-lang/lang meeting. The conclusion was that we should adopt @jseyfried's "option 2":
Specifically, we do eventually want shadowing semantics, and therefore it doesn't make sense to regress crates that are taking advantage of it, even if the current support is a bug.
jseyfried commentedon Feb 12, 2016
Ok, sounds good.
How should we fix the documentation for the example in this comment?
nrc commentedon Feb 14, 2016
@jseyfried Are talking about Rustdoc? I think listing a struct when it is only exported in a single namespace is OK (better than not listing it, since it is in fact exported in some sense). Perhaps adding notes for such situations would be nice.
petrochenkov commentedon Feb 14, 2016
By the way, what will happen with half-shadowed items in cross-crate scenarios?
Metadata doesn't care about namespaces currently, it will keep the half-exported items as whole items.
Then some of the conflicting names will be unpredictably ignored again due to
try_define
when this metadata is read.jseyfried commentedon Feb 14, 2016
@nrc Yeah, I was talking about Rustdoc. Thinking about this some more, I agree that it is OK to list a partially shadowed struct -- it looks like it would be very uncommon in the wild and we already have far more common cases of unnameable paths in rustdoc thanks to the distinction between visibility and nameability.
@petrochenkov Indeed, except they will be predictably ignored -- items are listed before re-exports in metadata so that when there is a conflict between an item and an import, the item will always win. This probably isn't the most elegant solution but it works for now.
petrochenkov commentedon Feb 14, 2016
Well, at least it doesn't depend on the phase of the moon.
Auto merge of #32814 - jseyfried:improve_duplicate_glob_detection, r=…
Auto merge of #36814 - petrochenkov:def, r=eddyb
petrochenkov commentedon Feb 19, 2017
This was fixed by stabilizing RFC 1560.
@jseyfried please reopen if something is missing.