-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
(Modules) Tracking issue for Picking a Module Path System variant #53130
Comments
Could you give more details about what has been implemented concretely, and what renaming operations are needed exactly? It comes down to: how can I start testing anything right now? A priori, I vote for |
cc @eddyb re. @sanmai-NL's question. |
#[feature(uniform_paths)]: allow `use x::y;` to resolve through `self::x`, not just `::x`. _Branch originally by @cramertj, based on @petrochenkov's [description on the internals forum](https://internals.rust-lang.org/t/relative-paths-in-rust-2018/7883/30?u=petrochenkov)._ _(note, however, that the approach has significantly changed since)_ Implements `#[feature(uniform_paths)]` from #53130, by treating unqualified `use` paths as maybe-relative. That is, `use x::y;`, where `x` is a plain identifier (not a keyword), is no longer the same as `use ::x::y;`, and before picking an external crate named `x`, it first looks for an item named `x` in the same module (i.e. `self::x`) and prefers that local item instead. Such a "maybe-relative" `x` can only resolve to an external crate if it's listed in "`extern_prelude`" (i.e. `core` / `std` and all the crates passed to `--extern`; the latter includes Cargo dependencies) - this is the same condition as being able to refer to the external crate from an unqualified, non-`use` path. All other crates must be explicitly imported with an absolute path, e.g. `use ::x::y;` To detect an ambiguity between the external crate and the local item with the same name, a "canary" import (e.g. `use self::x as _;`), tagged with the `is_uniform_paths_canary` flag, is injected. As the initial implementation is not sophisticated enough to handle all possible ways in which `self::x` could appear (e.g. from macro expansion), this also guards against accidentally picking the external crate, when it might actually get "shadowed" later. Also, more canaries are injected for each block scope around the `use`, as `self::x` cannot resolve to any items named `x` in those scopes, but non-`use` paths can, and that could be confusing or even backwards-incompatible. Errors are emitted only if the main "canary" import succeeds while an external crate exists (or if any of the block-scoped ones succeed at all), and ambiguities have custom error reporting, e.g.: ```rust #![feature(uniform_paths)] pub mod foo { use std::io; pub mod std { pub mod io {} } } ``` ```rust error: import from `std` is ambiguous --> test.rs:3:9 | 3 | use std::io; | ^^^ could refer to external crate `::std` 4 | pub mod std { pub mod io {} } | ----------------------------- could also refer to `self::std` | = help: write `::std` or `self::std` explicitly instead = note: relative `use` paths enabled by `#![feature(uniform_paths)]` ``` Another example, this time with a block-scoped item shadowing a module-scoped one: ```rust #![feature(uniform_paths)] enum Foo { A, B } fn main() { enum Foo {} use Foo::*; } ``` ```rust error: import from `Foo` is ambiguous --> test.rs:5:9 | 4 | enum Foo {} | ----------- shadowed by block-scoped `Foo` 5 | use Foo::*; | ^^^ | = help: write `::Foo` or `self::Foo` explicitly instead = note: relative `use` paths enabled by `#![feature(uniform_paths)]` ``` Additionally, this PR, because replacing "the `finalize_import` hack" was a blocker: * fixes #52140 * fixes #52141 * fixes #52705 cc @aturon @joshtriplett
@sanmai-NL Now that #52923 has landed, the next nightly should have both options available:
I'd suggesting trying the latter after upgrading to the edition, and report back if the ambiguity errors end up being too excessive. AFAIK, the upgrade involves taking a Rust 2015 crate, adding |
I absolutely despise the "anchored paths variant," and I am very excited to see that we're considering an alternative. Any alternative, honestly. >.> ...That said, uniform paths look great. :) I'd much prefer to let people use absolute paths (the anchored version) if they like, but not force people to do it. (No idea where the appropriate place to provide feedback for this would be, so I just left it here. Sorry.) |
Using #![feature(rust_2018_preview)]
#![feature(uniform_paths)]
use hex;
fn main() {
println!("hex {}", hex::encode("01"));
} I get this error: error: import from `hex` is ambiguous
--> src/main.rs:3:5
|
3 | use hex;
| ^^^
| |
| could refer to external crate `::hex`
| could also refer to `self::hex`
|
= help: write `::hex` or `self::hex` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]` whereas Because the code is working without |
@Nemo157 |
@archer884: What’s more interesting is your motivation to feel that way? |
As a user (who perhaps hasn't been paying as much attention as I should) I think the |
Not sure what you mean. Does #53427 (by treating each namespace independently) solve that for you? |
@sanmai-NL:
Either Eric Lippert or Anders Hejlsberg had an article on this awhile back: people want loud syntax for things at first, but then as time goes on they want the syntax to be unobtrusive and elegant instead. If we make long, annoying imports the standard (and ONLY) option, we will absolutely regret it.
"Maybe not today, maybe not tomorrow, but someday." :)
|
That’s an argument from authority, and a very aspecific one. Conciseness is a criterion independent from explicitness and also from simplicity. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The final comment period, with a disposition to merge, as per the review above, is now complete. |
See also: #53130 proposing to stabilize on uniform paths. |
[beta] resolve: Implement uniform paths 2.0 With this PR paths in imports on 2018 edition are resolved as relative in the scope in which they are written, similarly to any other paths. The previous implementation worked differently - it tried to resolve the import in the current module (`self::import`) and in the "crate universe" (`::import`), and then merge these two resolutions if possible. The difference is that the new scheme can refer to strictly larger set of names in scope - names from unnamed blocks, names from all kinds of preludes, including macros imported with `#[macro_use] extern crate`, built-in types/macros, macros introduced with `macro_rules`. This means strictly more potential ambiguities and therefore ambiguity errors, since we keep the rule that any two different candidate names in scope conflict with each other during import resolution. So this is a breaking change for 2018 edition, but it should be relatively minor. All paths that don't start with an extern crate are also gated with the `uniform_paths` feature, paths that refer to extern crates are not gated (so we effectively get something like "future-proofed anchored paths" on stable). Another difference is treatment of paths in visibilities (`pub(in path)`). Few people remember about paths in visibilities, so before this PR they still used the old 2015 rules even on 2018 edition. Namely, paths in visibilities were crate-relative, analogous to 2015 edition imports. This PR resolves paths in visibilities as uniform as well, or rather future proofs them in this direction. Paths in visibilities are restricted to parent modules, so relative paths almost never make sense there, and `pub(in a)` needs to be rewritten as `pub(in crate::a)` in the uniform scheme, de-facto cementing the discouraged status of non-`pub(crate)` and non-`pub(super)` fine-grained visibilities. This is clearly a breaking change for 2018 edition as well, but also a minor one. The in-scope resolution strategy for import paths mirrors what is currently done for macro paths on stable (on both editions), so it will continue working even if the "ambiguity always means error" restriction is relaxed in the future. This PR also significantly improves diagnostics for all kinds of resolution ambiguities, from the newly introduced import ones to pretty old "glob vs glob" conflicts. (That's probably what I've spent most of the time on.) Why beta: - This is a breaking change on 2018 edition. - This is a large PR, it's less risky to forward-port it to nightly, than back-port to beta. cc #55618 cc #53130 cc rust-lang/rfcs#1289 Closes #18084 Closes #54525 Fixes #54390 Fixes #55668 r? @ghost
[beta] resolve: Implement uniform paths 2.0 With this PR paths in imports on 2018 edition are resolved as relative in the scope in which they are written, similarly to any other paths. The previous implementation worked differently - it tried to resolve the import in the current module (`self::import`) and in the "crate universe" (`::import`), and then merge these two resolutions if possible. The difference is that the new scheme can refer to strictly larger set of names in scope - names from unnamed blocks, names from all kinds of preludes, including macros imported with `#[macro_use] extern crate`, built-in types/macros, macros introduced with `macro_rules`. This means strictly more potential ambiguities and therefore ambiguity errors, since we keep the rule that any two different candidate names in scope conflict with each other during import resolution. So this is a breaking change for 2018 edition, but it should be relatively minor. All paths that don't start with an extern crate are also gated with the `uniform_paths` feature, paths that refer to extern crates are not gated (so we effectively get something like "future-proofed anchored paths" on stable). Another difference is treatment of paths in visibilities (`pub(in path)`). Few people remember about paths in visibilities, so before this PR they still used the old 2015 rules even on 2018 edition. Namely, paths in visibilities were crate-relative, analogous to 2015 edition imports. This PR resolves paths in visibilities as uniform as well, or rather future proofs them in this direction. Paths in visibilities are restricted to parent modules, so relative paths almost never make sense there, and `pub(in a)` needs to be rewritten as `pub(in crate::a)` in the uniform scheme, de-facto cementing the discouraged status of non-`pub(crate)` and non-`pub(super)` fine-grained visibilities. This is clearly a breaking change for 2018 edition as well, but also a minor one. The in-scope resolution strategy for import paths mirrors what is currently done for macro paths on stable (on both editions), so it will continue working even if the "ambiguity always means error" restriction is relaxed in the future. This PR also significantly improves diagnostics for all kinds of resolution ambiguities, from the newly introduced import ones to pretty old "glob vs glob" conflicts. (That's probably what I've spent most of the time on.) Why beta: - This is a breaking change on 2018 edition. - This is a large PR, it's less risky to forward-port it to nightly, than back-port to beta. cc #55618 cc #53130 cc rust-lang/rfcs#1289 Closes #18084 Closes #54525 Fixes #54390 Fixes #55668 r? @ghost
Some follow-up issues:
|
Stabilize `uniform_paths` Address all the things described in #56417. Assign visibilities to `macro_rules` items - `pub` to `macro_export`-ed macros and `pub(crate)` to non-exported macros, these visibilities determine how far these macros can be reexported with `use`. Prohibit use of reexported inert attributes and "tool modules", after renaming (e.g. `use inline as imported_inline`) their respective tools and even compiler passes won't be able to recognize and properly check them. Also turn use of uniform paths in 2015 macros into an error, I'd prefer to neither remove nor stabilize them right away because I still want to make some experiments in this area (uniform path fallback was added to 2015 macros used on 2018 edition in #56053 (comment)). UPDATE: The last commit also stabilizes the feature `uniform_paths`. Closes #53130 Closes #55618 Closes #56326 Closes #56398 Closes #56417 Closes #56821 Closes #57252 Closes #57422
Stabilize `uniform_paths` Address all the things described in #56417. Assign visibilities to `macro_rules` items - `pub` to `macro_export`-ed macros and `pub(crate)` to non-exported macros, these visibilities determine how far these macros can be reexported with `use`. Prohibit use of reexported inert attributes and "tool modules", after renaming (e.g. `use inline as imported_inline`) their respective tools and even compiler passes won't be able to recognize and properly check them. Also turn use of uniform paths in 2015 macros into an error, I'd prefer to neither remove nor stabilize them right away because I still want to make some experiments in this area (uniform path fallback was added to 2015 macros used on 2018 edition in #56053 (comment)). UPDATE: The last commit also stabilizes the feature `uniform_paths`. Closes #53130 Closes #55618 Closes #56326 Closes #56398 Closes #56417 Closes #56821 Closes #57252 Closes #57422
This is a sub-tracking issue for the RFC "Clarify and streamline paths and visibility" (rust-lang/rfcs#2126)
as well as the internals post Relative Paths in Rust 2018.
The issue deals with revamping paths and making a decision about whether we should pick:
uniform_paths
variant.Proposed in Relative Paths in Rust 2018.
anchored_use_paths
variant.You have to use
self::
,super::
, andcrate::
, or an external crate name explicitly....See RFC: Clarify and streamline paths and visibility rfcs#2126).
uniform_paths
, #[feature(uniform_paths)]: allowuse x::y;
to resolve throughself::x
, not just::x
. #52923anchored_use_paths
Unresolved questions:
The text was updated successfully, but these errors were encountered: