Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upModules #2121
Conversation
withoutboats
added some commits
Aug 14, 2017
This comment has been minimized.
This comment has been minimized.
|
I like the proposal as a whole, but Otoh, we could make crate visibility the default, and use the existing |
withoutboats
added
Ergonomics Initiative
T-lang
labels
Aug 23, 2017
This comment has been minimized.
This comment has been minimized.
arthurprs
commented
Aug 23, 2017
|
I still have to carefully read everything but I feel that this proposal is underestimating the cost of adding 2 more keywords. |
TimNN
reviewed
Aug 23, 2017
| would be a valid way to invoke rustc by hand: | ||
|
|
||
| ``` | ||
| rustc src/lib.rs --modules src/*.rs src/**/*.rs |
This comment has been minimized.
This comment has been minimized.
TimNN
Aug 23, 2017
Contributor
Nit: For clarity, I think this should either be --modules "src/*.rs src/**/*.rs" or --modules src/*.rs --modules src/**/*.rs (otherwise src/**/*.rs would be a "free" argument).
This comment has been minimized.
This comment has been minimized.
TimNN
Aug 23, 2017
Contributor
In this example, are the arguments expanded by rustc or the shell? If they are expanded by rustc, I think the reasoning behind the following statement from the alternatives makes less sense:
We could also put the file-lookup in rustc, instead of cargo, and have rustc perform its own directory walk. We believe this would be a bad choice of layering.
Since rustc is already doing a directory walk, why not have only rustc do the directory walk.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
est31
Aug 23, 2017
Contributor
Should be pointed out in the RFC IMO. I've stumbled across the same question when reading the rendered doc.
This comment has been minimized.
This comment has been minimized.
XAMPPRocky
Aug 23, 2017
@withoutboats Expansion by shell would never work since there is hard limit on the number arguments you can pass to a program. 128KB worth or 1/4 of your stack size.
This comment has been minimized.
This comment has been minimized.
abonander
commented
Aug 23, 2017
•
|
I'd have to The Not to mention that this could break crates which published with broken Rust files that were unreachable with the current rules but would not be with the new rules. |
TimNN
reviewed
Aug 23, 2017
|
|
||
| * The file name is not a valid Rust identifier followed by `.rs`. | ||
| * The file is not in a subdirectory of the directory containing the root | ||
| module. |
This comment has been minimized.
This comment has been minimized.
TimNN
Aug 23, 2017
Contributor
Depending on how this "subdirectory of" check is implemented it could get pretty tricky:
- Do the prefixes given to
--moduleshave to match? If not: - How are paths normalised? How are soft/hard links handled?
In most cases this probably does not matter, but it may still be worth considering.
This comment has been minimized.
This comment has been minimized.
withoutboats
Aug 23, 2017
Author
Contributor
These are implementation details that don't need to be decided at the RFC stage. This is just a sanity check that we can transform the directory into paths.
This comment has been minimized.
This comment has been minimized.
|
I like the Items marked as |
This comment has been minimized.
This comment has been minimized.
This is why the cargo flag is not defaulted to |
This comment has been minimized.
This comment has been minimized.
repax
commented
Aug 23, 2017
•
|
I'm wondering about the
Edit: Also, we have |
This comment has been minimized.
This comment has been minimized.
|
Constraints for the |
nikomatsakis
reviewed
Aug 23, 2017
| actually `pub`. We make this much clearer by the combination of two choices in | ||
| this RFC: | ||
|
|
||
| - All items that are `export` (equivalent of today's `pub`) must *actually* be |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Aug 23, 2017
Contributor
Nit: I believe this is out of sync with the current version of the RFC.
This comment has been minimized.
This comment has been minimized.
epdtry
commented
Aug 23, 2017
|
For file loading, I still think it would be better to move the directory traversal into |
This comment has been minimized.
This comment has been minimized.
repax
commented
Aug 23, 2017
•
|
First off, I'm really excited about this RFC! Now, how about just
✓ Shorter tends to be better than longer. use priv::foo::Bar;
::priv::foo::Bar;✓ It needs to be sensible as a visibility (an adjective is strongly preferable). |
This comment has been minimized.
This comment has been minimized.
|
@repax: The problem that I have with |
This comment has been minimized.
This comment has been minimized.
repax
commented
Aug 23, 2017
•
|
@TimNN: Yeah, I think I confused myself there. I dunno. |
This comment has been minimized.
This comment has been minimized.
|
@repax: That's exactly what I'm saying, if I understand your analogy correctly:
So saying something is private makes it less private than if I hadn't said anything, which is what I'm having problems with. |
est31
reviewed
Aug 23, 2017
|
|
||
| During the design process, we considered other, more radical redesigns, such as | ||
| making all files "inlined" into their directory and/or using the filename to | ||
| determine the visibility of a module. We've decided not to steps that are this |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
repax
commented
Aug 23, 2017
|
@TimNN: This is tricky, indeed. But Besides, |
This comment has been minimized.
This comment has been minimized.
phil-opp
commented
Aug 23, 2017
•
|
I don't like that I have to change almost all The previously proposed special visibility for items that are part of a library's public API made much more sense to me. For me, something like the following would feel most natural:
This would minimize code churn, since only the (few) exported types/functions of libraries need new visibility qualifiers. |
This comment has been minimized.
This comment has been minimized.
|
My comment is very non-verbose to minimize noise. On the preceeding proposal I expressed concerns that privacy level was restricted to three levels (public to the world, public to the crate, private to the module), but that was based on a misunderstanding of mine on the RFC, and I think this RFC doesn't feature this problem either as you can restrict privacy of entire modules via the mod keyword. Stuff I like
Stuff I'm not really a great fan of
My main concerns
Summing it all up |
This comment has been minimized.
This comment has been minimized.
I appreciate your point, however, for many people the idea of "declaring a module" has proven to be a major source of confusion. In other words, |
This comment has been minimized.
This comment has been minimized.
|
While |
This comment has been minimized.
This comment has been minimized.
|
As I raised on the previous thread and @TimNN already touched on as well, I think |
This comment has been minimized.
This comment has been minimized.
|
|
Keats
reviewed
Aug 24, 2017
| function, etc), without creating declared items of those names at this point in | ||
| the module hierarchy. | ||
|
|
||
| `use` statmeents with a visibility (such as `pub use`) are deprecated, and |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
I would like to put another voice towards splitting this RFC and moving the autoloading to another RFC. For the record (again, from the other RFC) - I'm against changing the module loading method to be implicit in general, but if it had to be done - using the current proposal of passing a set of globs to rustc is preferable to explicitly listing files (or worse, having rustc know of cargo's rules) |
This comment has been minimized.
This comment has been minimized.
From how I interpret the RFC, you will have to either make a |
This comment has been minimized.
This comment has been minimized.
General notesAs a preamble, I would like to note that this RFC acts as if RFC #2088 will land for sure, and AFAIK this has not been decided yet. The same can be said about the reliance on checkpoints in this RFC. I would also like to note that even if a survey said that beginners have issues with the current system, it doesn't automatically mean that the current system should change, and it doesn't mean that the new system (that introduces many very invasive breaking changes) will not make everyone's life more complicated at scale. MotivationThe survey of crates.io didn't include most largest crates, such as the ones in Servo, that uses way more local imports than external ones. In projects that cannot be split into multiple crates, "If a crate is renamed, you do not need to rename all internal imports" shouldn't be an argument in favour of this RFC, that sounds like optimising for crate renaming, which is a very rare thing. The RFC mentions the previous take, where all files were inlined in their directories and directories were modules. It also says that "We've decided not to steps that are this radical right now." Please remove the "right now". Things I don't likeI think that the very existence of implicit module loading will be an additional burden for me to maintain things or contribute to satellite dependencies of Servo that aren't handled by us directly. I think that I have a vague feeling that this RFC will make future versions of the language unable to ever have a module system that is useful for other purposes than simple namespacing (parameterised modules, etc). I think that the mandatory explicit visibility bring absolutely nothing to the table and even hurts ergonomics. Why make Things I think should be blockersThe RFC should not ever, ever land without the automatic migration tool being ready. Things I like |
This comment has been minimized.
This comment has been minimized.
|
I'm gonna write a comment that I've been thinking about since the previous iterations of this RFC: The thing I call the "Rust Module System" in my mind is dead simple:
The fact that a few So, to me, the whole complexity comes from visibility, use and paths, since these topics are more interconnected than how modules are declared. However the core rules around the three topics are also pretty simple, in my opinion: The core rules around visibility are simple:
The rules around paths are simple:
The primary rules around
An then there are some rules, or interaction between rules, which I think cause the additional complexity:
In summary: I think the core rules of the current system are pretty simple (and, more importantly, pretty uniform): They fit on a single sheet of paper. However there are a few rules which are themselves either complex or confusing (the last four rules above). So in my opinion the RFC should focus on improving the situation / learnability around those rules (or accept, eg. for I think this RFC does an admirable job of that with eg. removing extern crates from the root namespace and adding the |
This comment has been minimized.
This comment has been minimized.
FYI, since rust-lang/rust#42125 landed, there's only one final push required to resolve this for good - make "private-in-public" a lint and not an error and make it use more intuitive reachability-based heuristics (lints can use heuristics, unlike errors). |
This comment has been minimized.
This comment has been minimized.
burdges
commented
Aug 24, 2017
•
|
I also believe the survey of crates.io is flawed, like @nox says. I'd suggest surveying some large projects like rustc, cargo, servo, ring, and their dependencies. As an aside, there is a cost to users when crates break themselves up into many smaller crates, like the RustCrypto project did, and like the rand crate is discussing, if only because the documentation becomes less cohesive. These crates have security reasons for doing so, in that a person auditing users of the code can see at a glance if approved or unapproved algorithms get included. And tokio makes sense too, due to a very complex dependency graph and that users benefit from understanding. We should not take these hierarchies of micro crates as an ideal though.
I'd love to know how parameterised modules and module aliases fit with this story. I'd assume the module must then contain a line |
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.
rpjohnst
commented
Aug 24, 2017
|
Another way to look at it is to go back to @aturon's blog post or the RFC's motivation section which described the issues we're trying to solve. The things auto-loading seems aimed at are "too many declaration forms"/"lots of frontloaded syntax," "filesystem organization," "multiple keywords import things," and "repetition." Some of these goals it still meets, at least individually. However, many of these goals it no longer serves quite as much, or at all. So, while implicit module loading is tied into the local visibility reasoning goal, I'm beginning to think it's not worth it, for a few reasons:
|
This comment has been minimized.
This comment has been minimized.
|
One thing I haven't seen discussed is how much an IDE would help the beginner approach the current module system. It seems to me that most of the pains could be avoided at the IDE level. |
This comment has been minimized.
This comment has been minimized.
|
Some editorial points: (I’ll leave opinions for a separate comment.) What is seemingly the same visibility keyword is called What is seemingly the same path prefix is called
Grammatically, part of this first sentence seems to be missing. What about these items? Are they disallowed? (Guessing based on context.) “They” in the second sentence seems to refer to these items, but I think something else (the crate’s author?) was intended.
Other parts of the RFC suggest (by using “must”) this is an error rather than a warning. Which is it?
Wouldn’t that need to be |
This comment has been minimized.
This comment has been minimized.
stevenblenkinsop
commented
Aug 24, 2017
•
|
The attempt to modularize the modules rfc backfired somewhat because the components were overly coupled, so changes in one part caused undetected breakages elsewhere in the system ;) (something something non-local reasoning) |
This comment has been minimized.
This comment has been minimized.
In this proposal, export is not a visibility modifier. It is statement whose only purpose is to re-export an item from another place. In fact, a visibility modifier can (and usually would be) used with For example,
I believe the correct way to parse the sentence is this: (Items marked pub inside of (files which are not public)) are not visible outside of this crate, because (the full path to that item) is not pub. i.e. the items in question are not public to the world even though they are marked
I think it will be a warning at first; then in a later epoch, it'll be a hard error. |
This comment has been minimized.
This comment has been minimized.
Or increased focus on The Book's chapters on modules... |
This comment has been minimized.
This comment has been minimized.
ExpHP
commented
Aug 24, 2017
|
Yesterday, I tried to start cataloging all of the various modules proposals from a birds-eye view in an attempt to identify the differences between them, to record their various advantages/disadvantages, and to help understand the cascading changes in design. I wanted to try and understand the complicated design space that we're dealing with. ...well, that was the plan. After doing this so far, however, it feels to me like the feature of automodules actually is orthogonal to the rest of the design. I notice that, between these two RFCs, this one provides an improved design for |
This comment has been minimized.
This comment has been minimized.
|
Also, would it be good to create a separate RFC for the public-in-private lint. It seems like we would want something like that whether this RFC passes or not, and I think it can be done in a forward-compatible way... |
This comment has been minimized.
This comment has been minimized.
stevenblenkinsop
commented
Aug 24, 2017
|
The only problem with the public-in-private lint without this rfc is it forces people to write Presumably the proposal would still have to include a migration tool to do the rewriting in existing code. |
This comment has been minimized.
This comment has been minimized.
|
We could just make the lint have a default of
Sure, it's not super pretty and it's not short, but I think it would do nicely until we have a good solution. |
This comment has been minimized.
This comment has been minimized.
We have done this, twice already. It hasn't helped. Nobody has come up with a magic tutorial that makes people understand things easily. And in fact, @carols10cents , in one of the earlier threads, showed a revised version of the chapter with these changes, and it was a lot better. |
This comment has been minimized.
This comment has been minimized.
stevenblenkinsop
commented
Aug 24, 2017
•
|
The whole point is to push deployed code towards having the correct visibility modifiers. If it's opt-in, most code won't use it, so it won't have the desired effect. Yeah, people who particularly care can opt in, but that doesn't do anything to address the readability issue when reading other people's code. |
This comment has been minimized.
This comment has been minimized.
There's one more thing - how compiler's own diagnostics can help the beginner to approach the current module system! Currently there's nearly zero (maybe literally zero) help messages related to module loading (missing EDIT: The first module discussion thread on internals had an immensely useful user report about this - https://internals.rust-lang.org/t/revisiting-rusts-modules/5628/33 |
This comment has been minimized.
This comment has been minimized.
It is still an intermediate step, though. And whatever the final solution is, I think it will probably include such a lint anyway... |
This comment has been minimized.
This comment has been minimized.
|
The modules saga has truly broken all records for comment velocity! After some soul-searching discussions among the lang team, and considering the small amount of time left before the impl period, here's what I'd like to propose:
The new main RFC here involves no new keywords, and can be done purely with deprecations; it does not require a new epoch. I believe it retains many (but not all) of the learnability benefits of the current RFC. It enables us to explore those other benefits in a slower-paced way, through an experimental RFC. @withoutboats is going to be tied up with moving house, so I plan to write this new main RFC in the next couple of days. I expect it to be much shorter and to draw a lot from the Meantime, I'm gonna close this one out... |
aturon
closed this
Aug 24, 2017
This comment has been minimized.
This comment has been minimized.
|
@aturon I'm sad that we'll continue to need to write mod statements, but I think that this is the right choice for now. |
This comment has been minimized.
This comment has been minimized.
Can path and visibility changes be submitted as separate RFCs?
Oh, this is nice. |
This comment has been minimized.
This comment has been minimized.
emk
commented
Aug 25, 2017
•
|
(EDIT: Ah, sorry, it looks like I missed the closing above. I started writing this yesterday, and much of it has been overtaken by events. The underlying reactions, however, might still be useful to someone.) Speaking as commercial user of Rust who's been bringing multiple in-house developers up to speed, and who already has a non-trivial code base to migrate, my feelings about this whole plan are mixed: some positive, some negative, and some wary. This is also the first time I've seen the whole "epochs" RFC, which is apparently a done deal. This is what I get for not reading r/rust all the time.
So overall, my personal verdict is: This change is too large, and it would reduce my trust in Rust's stability and fitness for commercial use. If this is a one-time thing with excellent migration tools, then I can grudgingly accept it to improve Rust onboarding. But if the typical epoch is going to make changes this big, I would need to spend a lot more time defending Rust to my colleagues at work. The mere fact that this will break example code on Stack Overflow is a big deal. Basically, the thought running through the back of my head is "We've had a golden era since Rust 1.0, but is this the end? Will I need to keep up with constant change again?" I simply have too many Rust crates, both at work and personally, to ever chase the upgrade treadmill again. The more I look at the automatic migration tools, parallel epoch support, etc., the more I realize that this isn't an entirely fair reaction. But that's my underlying gut reaction. And that will probably be the gut reaction of some of my colleagues, at least until I explain the whole epochs plan to them, which will take time. Like it or not, those kinds of conversations are also part of the developer experience that's being proposed. |
This comment has been minimized.
This comment has been minimized.
|
The new RFC is up! |
withoutboats commentedAug 23, 2017
Here is another RFC describing a change to the Rust module system (hopefully the last for the near future).
Because it is a relatively large RFC, I have broken the text into multiple files. You can find the rendered root of the RFC here.
The overview document gives a high level overview of the proposed new system and how it differs from the current system.
See RFC #2108, the previous module RFC, for previous work (and links to even more previous work).
For people involved in the previous discussion, here are the highlights of the differences. I would say in summary its a similar skeleton, but with some very significant changes to the skin to make it a much less radical departure.
The
localkeyword: Instead of changing the meaning ofpub, a new visibility calledlocalis added for restricted visibility between private and pub. To make this meaning of local easier to learn pedagogically, thecrate::form of absolute paths have been changed to be writtenlocal::.modstatements: Mod statements continue to exist instead of being removed. Even when autoloading modules, they will still be used to control visibility (such as making them more public or more private).The
exportkeyword: Now that its not a visibility,exportis just a standard mechanism for re-exporting things, similar to ausestatement but optimized for this use case.Autoloading opt outs: Two mechanisms of opt out for the autoloading mechanism are added, an
#[ignore]attribute for temporarily opting out of loading a particular file, and a Cargo.toml flag which prevents cargo from preparing the--moduleslist at all.Quoting this from the previous RFC:
As a final note: this is a polite reminder that the RFCs repo, like all Rust project venues, is governed by the Code of Conduct and also that we, the RFC authors, are acting in good faith (honestly!). Please always be charitable in disagreement.😄 🌈 ❤️