-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Custom preludes #890
RFC: Custom preludes #890
Conversation
This is NICE! 👍 👏 |
I love how it democratizes preludes; it should also help a lot for embedded Rust use-cases. Unfortunately I think this is one of those ideas that looks great on paper but ends up causing headaches in practice. This has the potential of creating a project/company level language "fork," in the sense that the top-level names that one would expect to be present could be entirely different from project to project. At Google, we have a very large, unified C++ codebase where many names from You basically end up with a custom language dialect that's slightly different, but different enough. New developers won't know it, they'll hate having to learn it and any code that's been written for the "standard" dialect can easily fail to compile in yours. I'd advise extreme caution here. I've seen the consequences of a custom C++ "prelude" in a large codebase and it's widely considered to be a mistake. DISCLAIMER: My opinions are mine and mine alone; I speak only for myself, not my employer. |
This still allows only the use of one prelude. But what if I need the IO "prelude" and the science math lib "prelude" in an application. Here I can't use this prelude property, right? So I would prefer using standard imports as used today. Rust already has really many features, and I do not think that it needs this kind of syndactic sugar. |
@pyfisch isn't that exactly what the Application example section shows how to do? |
I see it. So you can create a custom prelude for your application. Ok, looks reasonable. |
+1 I need this. I have a trait with a method |
@mahkoh Another way to make that less painful would be
(Still boilerplate, but not as much - not for each item you want from the prelude.) |
Yeah, one of the first things I looked for with Rust modules was Haskell's |
This is great! |
hey now that we're back from our RFC vacation how about RAMMING THIS THROUGH!! 💪 😁 👊 (or at least giving an update :) I do think that // glob import from some::module _except_ for one, two, and three
// this makes it clear that we're _definitely_ not using the `one`, `two`, or `three`
// from some::module
// if we see those items in the code then they're
// most likely from the current or other module
use some:module::* hiding {one, two, three};
// don't import one, two, three from the 'currently set' prelude
// would probably make prelude at least a context-dependent keyword though :/
// this is just an example syntax
use prelude hiding {one, two, three};
// another alternative would probably be
hiding {one, two, three};
// it also lets you glob import modules that would otherwise clash
// due to their contents, this way you can simply exclude those items that clash
// assume first and second contain an item `common`
use first::* hiding {common};
use second::*; Personally I think this explicitness is what I expect from Rust, and I think it should at least help with some of the concerns about making it difficult to tell what comes from where. |
@blaenk :) I'll raise this RFC at the weekly meeting today, just to garner more feedback from the team. It's been a bit on the backburner, since it's not really a 1.0 back-compat priority. |
Alright that's fine! |
An alternative to putting an annotation on a module is to use a crate attribute instead, which would presumably be a little more visible, and more obvious that it's a per-crate option. The example I used in #743 was |
Should we allow tagging For example, if I publish an alternative prelude called #[prelude] extern crate awesome_prelude; instead of this: #[prelude]
mod prelude {
extern crate awesome_prelude;
pub use awesome_prelude::*;
} This pattern may be useful for larger frameworks, with many component crates sharing a common core. |
@aturon do you feel we are ready to make a decision here? |
Since this has sat around for so long without movement, I'd suggest that is an indication it is not a pressing matter and we can punt it further. |
:( On Wednesday, June 10, 2015, Brian Anderson [email protected]
|
FWIW, I ended up not pushing on this largely due to the concerns that @Valloric raised (and the 1.0 push). While this RFC would have some serious ergonomic benefits for external crates, it does carry some hard-to-quantify risks about fragmenting the language into "prelude dialects". It'd be useful to gather some evidence, in the form of painful repeated |
Raising again now that #1184 has been applied. What is the reasoning for using a module attribute over a crate attribute? I would expect a crate-level attribute nominating a prelude path would be easier for users to locate and the compiler to handle than a magic marker on the prelude module. @aturon Could you add the following to the RFC as an alternative? |
Hear ye, hear ye. This RFC is moving to final comment period. |
#[prelude] | ||
mod prelude { | ||
// std actually provides multiple preludes now | ||
pub use std::prelude::v1::*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So to use this, I have to figure out what the current "default" prelude is, somehow? I think in the absence of no_std
, the default prelude should still be included, with this prelude being added.
Apologies if a dumb question, but in another life, I've seen problems with this and syntax-expansion style macros. That is, assume there's a macro in the standard prelude, and it expands into code that references other prelude types. While you can run into problems with that by shadowing today (e.g., https://play.rust-lang.org/?gist=baeb5e0af8c23be403b2&version=stable ), right now it would be pretty obvious because you either have a glob import or a shadowing definition of the type within the same module. With custom preludes, things are a little more complicated, as it could lead to some pretty wonky errors that require non-local reasoning to puzzle through. At the very least, a couple of options are:
|
@larsbergstrom The right solution to this issue is macro hygiene: Names in macros should be resolved in the context the macro was defined in, not in the context the macro is used in. I don't know what the current status of macro hygiene in Rust is, though. |
👍 I think the restriction to a root module is enough that, once you're aware custom preludes exist, it shouldn't cause any major problems in tracking down symbols. |
I, like @aturon, agree with @Valloric's original thoughts and feel the same as @brson. I haven't felt the need for this in any projects recently and I feel like we may want to get more traction with what we've got today before we dive into custom preludes. |
In most cases I would like to have this feature is when:
Today some of the ergonomic issues are solved by reexporting, which increases risk of namespace collisions. This could be better by organizing a custom prelude per application. I have thought a bit of how this would affect navigating larger libraries, and I believe it could solve some pain points:
Other things:
Overall it is a +1 for me. |
At the language subteam meeting, we decided to close this RFC pending stronger motivation. This might be a good addition to the language, but there doesn't seem to be urgent need at this time, and it's better to give things time to evolve and focus on other priorities. |
I would only add 1 thing. Loading custom prelude should be disabled by default and there should be additional option |
2 years have passed. May we should consider reopen this again? |
👍 100%, a tad annoying to be using alloc and not have the normal std prelude things. |
I would prefer to leave this closed. If you want a custom prelude, you can easily create a |
I like this because Implicit prelude to In that case, I think this would be better to be a "crate-wide" feature. For example, this imports symbols in
Or by compiler flag.
Or by Cargo configuration.
If you want to import multiple symbols from multiple crates, you need to build your own "aggregation crate". That would be better than making feature more complicated. |
Add a
#[prelude]
attribute that can be applied to a single module atcrate root to serve as a custom prelude for that crate.
Thanks to @XMPPwocky for helping develop and prototype these ideas!
Rendered