-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
resolve: Privacy rules for re-exports can be too restrictive #31783
Comments
Well, I have more interesting examples though, in which |
I agree that the practical impact is very small, but I do think it is inconsistent to be able to re-export a I think of I'm definitely interested in the examples -- not sure what properties means in this context. |
In this case
I think this is going to change when proper glob shadowing is implemented to support cases like
but there are some details, I'll elaborate later. |
Good point. To be fair though, it would be an unused import warning if a glob pattern didn't match anything. It actually might be a good idea to not allow an empty glob import -- I don't think anyone would do that intentionally.
mod foo {
pub fn f() {}
fn g() {}
} Right now |
There's also precedent here -- this compiles: mod foo {
mod bar { pub fn f() {} }
pub fn bar() {}
}
// This effectively imports `foo` in the value namespace. I say "effectively" because
// trying to use the imported name `foo` in the type namespace is a privacy error,
// not an unresolved name error.
use foo::bar;
fn main() {
bar();
// bar::f(); // If this line were uncommented, the import of `foo` would be a privacy error.
} |
|
Theoretically, an import with Note: this currently compiles, but I'm not sure it should
it allows to observe one initial step of the bifurcation mentioned above
|
Interesting. I think that example should definitely not compile. |
This seems to be already done in globs - |
After some experimenting, I think there are only two basic scenarios, and there's a simple scheme covering both concrete imports
Isolated
If
Isolated
If This scheme can be straightforwardly extended to support Isolated
The visibilities |
Interesting, I like these semantics.
|
After #31726, it will be straightforward to implement the setup you describe (i.e. private imports are proper items, globs can import private items, unused ambiguous glob-imported names are OK, multiple imports of the same item are OK, items and named imports can shadow globs). The current plan seems to be for the RFC proposing these changes to also propose a macros 2.0 system with new hygiene rules and the ability to import and use macros like any other item (changes that I support). However, I think the new import semantics should get their own RFC before (or beside) macros 2.0 since the new import semantics are much easier to implement, backwards incompatible (theoretically -- hopefully not in practice), more immediately useful (imo), and already are partially implemented by accident. What do you think? |
Sure, if you are already working on it, then why wait for macros 2.0, @nrc can review the RFC and ensure it's compatible with the new macro system. |
What I don't like in this #31783 (comment) scheme (and in the current scheme as well) is that resolution depends on privacy. I.e. to determine the import set and well-formedness for (1)
we need to resolve paths Can we come up with a scheme not using privacy information in any way in |
// If the type `root::bar` is `root::foo::bar -> root`, then `pub(root::bar)` is public and the glob is shadowed.
// If the type `root::bar` is `root::foo`, then `pub(root::bar)` is private to `foo` and the glob is not shadowed.
mod root {
mod glob_imported {
pub use root::foo as bar;
}
mod foo {
pub fn bar() {}
pub(root::bar) use root as bar;
}
use root::glob_imported::*;
use root::foo::bar;
}
// The same thing happens here, except that the bindings are not stable in either
// configuration instead of being stable in both configurations.
mod root {
mod glob_imported {
pub use root as bar;
}
mod foo {
pub fn bar() {}
pub(root::bar) use root::foo as bar;
}
use root::glob_imported::*;
use root::foo::bar;
} |
It would be doable to implement such a scheme, but it would add quite a bit of complexity. |
Maybe we could only allow It seems excessive to allow all paths since all we need to express is a De Bruijn index -- the paths |
I expected shadowing to precede privacy checks. But it still leaves "glob vs glob" conflicts. And they need to be resolved based on privacy, otherwise using two globs in one module could lead to unpredictable conflicts due to implementation details. Yeah, it seems like restricting paths in |
@petrochenkov Thinking about this some more, I strongly prefer your semantics over my alternative. Under your semantics, the following would compile today, right? pub fn foo() {}
mod foo { pub fn f() {} }
mod bar {
pub use foo; // This publicly imports `foo` in the value namespace and privately imports `foo` in the type namespace.
fn g() { foo::f() }
}
fn main() {
bar::foo();
} |
Yep. Edit: And with |
Implement `pub(restricted)` privacy (RFC 1422) This implements `pub(restricted)` privacy from RFC 1422 (cc #32409) behind a feature gate. `pub(restricted)` paths currently cannot use re-exported modules both for simplicity of implementation and for future compatibility with RFC 1560 (cf #31783). r? @nikomatsakis
This was fixed by stabilizing RFC 1560. |
The text was updated successfully, but these errors were encountered: