Skip to content

Stabilize uniform paths on Rust 2018 #55618

Closed

Description

@withoutboats

@rfcbot fcp merge
cc #53130

This issue is to track the discussion of the following proposal:

I propose we stabilize the uniform_paths feature in Rust 2018, eliminating the anchored_paths variant. I further propose we backport this stabilization to version 1.31 beta, so that all stable versions of Rust 2018 have this feature.

We've taken informal polls about this question in a paper document. Most of the lang team has favored uniform_paths, I and @cramertj were the only two members who initially favored anchored_paths. Yesterday, we discussed this in the lang team video meeting; in the meeting we sort of crystallized the various pros and cons of the two variants, but didn't reach a consensus.

In the time since the meeting, I've come around to thinking that stabilizing on uniform_paths is probably the best choice. I imagine @cramertj has not changed his mind, and though he said in the meeting he wouldn't block a decision, I hope we can use this FCP period to see if there's any agreeable changes that would make uniform_paths more palatable to him.

I've also written a blog post summarizing the meeting discussion and how my position has evolved, which provides more context on this decision.

I also want to make sure we continue to get community feedback as we reach this final decision! Please contribute new thoughts you have to the discussion. However, we will hopefully make this decision within the next few weeks, and certain proposals are out of scope. Any third proposal which is not completely backwards compatible with the current behavior of paths in Rust 2018 is impossible to ship in Rust 2018 at this point. Variations on anchored or uniform paths that are backwards compatible may be considered, but that also seems unlikely.

Activity

  1. withoutboats commented on Nov 2, 2018

    @withoutboats
    ContributorAuthor

    @rfcbot fcp merge

  2. rfcbot commented on Nov 2, 2018

    @rfcbot

    Team member @withoutboats has proposed to merge this. The next step is review by the rest of the tagged teams:

    Concerns:

    Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

    See this document for info about what commands tagged team members can give me.

  3. added
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.
    on Nov 2, 2018
  4. joshtriplett commented on Nov 2, 2018

    @joshtriplett
    Member

    @withoutboats Thank you for your detailed writeup, as well as your careful and considered evaluation.

    Having been the sole opposition of more than one language proposal in the past, I would like to explicitly extend the following invitation to @cramertj: If you feel you need more time to write up some thoughts on how uniform_paths could adapt to better meet the needs of Rust users in your group and elsewhere at Google, as well as any concerns about uniform_paths that didn't make it into yesterday's discussion as captured by @withoutboats' writeup, please feel free to either register a concern or simply state that you'd like more time. This is not a vote, and despite rfcbot's default behavior for what it takes to move forward with an FCP, I'd like us to reach a full consensus if possible.

  5. nikomatsakis commented on Nov 2, 2018

    @nikomatsakis
    Contributor

    please feel free to either register a concern or simply state that you'd like more time

    It's good to say it explicitly, of course, but -- to be clear -- I feel this is always true for any FCP =)

  6. Centril commented on Nov 2, 2018

    @Centril
    Contributor

    Excellent writeup @withoutboats. ❤️

    Report & Tests

    @rfcbot concern stabilization-report-and-tests

    Before we stabilize uniform_paths, I think we need a stabilization report that documents what behavior is being stabilized (and what is not), and tests for that behavior. Since @petrochenkov and @eddyb have been at the forefront of implementing the behavior, maybe they could write up the report?

    File-centric behavior

    @rfcbot concern file-centric-behavior

    As for what we're going to stabilize here, @nikomatsakis noted in the paper document that a more file-centric adaptation of uniform_paths is favourable such that you may write:

    use std::sync::Arc;
    
    mod foo {
        mod bar {
            // uses the `use` from parent module, because it is in the same file
            fn baz() -> Arc<u32> { ... }
        }
    }

    Benefits

    The file-centric approach is beneficial mainly because it is quite common for languages to take such an approach and Rust is the odd fish in the bunch; By adopting an approach where the above snippet is legal, the speed-bump when learning Rust can be reduced. For example, in Java, inner classes can see the imports at the top of the file.

    Another benefit of the file-centric approach is that you no longer have to write the use super::*; boilerplate, which is arguably a misfeature, anymore. This makes writing unit tests more ergonomic:

    use some_crate::Thing;
    
    fn foo(x: Bar) -> Baz { ... }
    
    #[cfg(test)]
    mod test {
        // use super::*;
        // ^-- you don't have to do this anymore.
    
        ...
    }

    Drawbacks

    I see two principal drawbacks with the file-centric behavior:

    1. It encourages writing large files and thus may diminish the maintainability of large projects.

    2. Inline modules are no longer units that can be so easily refactored. For example, if you want to move an inline mod foo { ... } into a dedicated file, then you may need to scroll up to the beginning of the file and copy the use statements. This can be mitigated with IDEs -- but not everyone have those.

    One mitigating factor here is that it is unlikely to have inline modules which nest; the most common use of inline modules are for unit tests or for small modules that contain platform specific behavior -- in the language team meeting, everyone agreed that this was the case and that nested inline modules were not commonly used.

    Conclusion

    All in all, while I was initially somewhat skeptical about the file-centric behavior, I think it is in line with one of the core goals of uniform_paths -- to make the module system intuitive and easy to learn. Therefore, I'd like to propose that we incorporate the file-centric behavior into the stabilization (EDIT: or at least make it possible after stabilization...).

    Why does it have to happen now? Consider the following (playground):

    // Nightly, Edition 2018 on.
    
    #![feature(uniform_paths)]
    
    // Let's assume that there's a crate `foo` in the extern prelude with `foobar` in it.
    
    mod foo {
        pub fn foobar() -> u8 { 1 }
    }
    
    mod bar {
        fn barfoo() -> u8 {
            // With the current `uniform_paths`,
            // there's no conflict as far as the resolution system sees it.
            //
            // Thus, if `foo` is in the extern prelude, it will resolve to the
            // `foo` crate and not `foo` the sibling module. If we allow that
            // to pass, then a *breaking change* will be the result if we change
            // to the file centric behavior.
            foo::foobar()
        }
    }
  7. lucozadeez commented on Nov 2, 2018

    @lucozadeez

    Apologies if this has already been considered but would extern::foo work to disambiguate uniform paths?

    So the logic would always be

    • crate::foo:: for modules in the crate
    • extern::foo:: for external modules
    • foo:: for submodules if there is a matching submodule or external if not

    It has the advantage of using an existing keyword. I couldn't see any reason for there to be a parsing ambiguity but I could be wrong there.

  8. Centril commented on Nov 2, 2018

    @Centril
    Contributor

    @lucozadeez

    Apologies if this has already been considered but would extern::foo work to disambiguate uniform paths?

    To disambiguate, you can write ::foo instead; this will have the same effect.
    We could also permit extern::foo but that would be sort of redundant (more than one ways to do it without clear benefits...).

    I couldn't see any reason for there to be a parsing ambiguity but I could be wrong there.

    I don't think there would be any ambiguity.

  9. joshtriplett commented on Nov 2, 2018

    @joshtriplett
  10. nikomatsakis commented on Nov 2, 2018

    @nikomatsakis
    Contributor

    @Centril

    Before we stabilize uniform_paths, I think we need a stabilization report that documents what behavior is being stabilized (and what is not)

    😍 Yes please! 😍

  11. petrochenkov commented on Nov 2, 2018

    @petrochenkov
    Contributor

    I think we need a stabilization report that documents what behavior is being stabilized (and what is not), and tests for that behavior

    Implementation is in progress, so the behavior will change slightly.
    I landed some preliminary refactorings last weekend and hope to finish the work this weekend.
    I want to do it in such way that uniform paths are always enabled on 2018, but gated if actually used, so we get feature gate errors instead of "unresolved name" errors.
    This is possible because "anchored paths with future-proofing" is a strict subset of uniform paths.

    I'd prefer to test the new implementation for one more cycle and not backport stabilization to 1.31.

  12. nikomatsakis commented on Nov 2, 2018

    @nikomatsakis
  13. nikomatsakis commented on Nov 2, 2018

    @nikomatsakis
  14. 92 remaining items

  15. Centril commented on Dec 29, 2018

    @Centril
    Contributor

    @rfcbot resolve stabilization-report-and-tests

    Done in #56759.

  16. aturon commented on Jan 9, 2019

    @aturon
    Contributor

    @rfcbot resolve implementation

  17. added
    final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.
    on Jan 9, 2019
  18. rfcbot commented on Jan 9, 2019

    @rfcbot

    🔔 This is now entering its final comment period, as per the review above. 🔔

  19. removed
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    on Jan 9, 2019
  20. added 2 commits that reference this issue on Jan 12, 2019
  21. ErichDonGubler commented on Jan 12, 2019

    @ErichDonGubler
    Contributor

    I'm confused. Shouldn't this issue remain open until the FCP completes?

  22. Centril commented on Jan 12, 2019

    @Centril
    Contributor

    @ErichDonGubler well, due to time constraints it will already be in 1.32 and FCP in #56759 (comment) will complete in 1 day.

    @rfcbot cancel

  23. removed
    final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.
    disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.
    on Jan 12, 2019
  24. added a commit that references this issue on Apr 27, 2019
  25. added a commit that references this issue on Apr 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions