Skip to content
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: Stabilize std::prelude #503

Merged
merged 3 commits into from
Dec 20, 2014
Merged

RFC: Stabilize std::prelude #503

merged 3 commits into from
Dec 20, 2014

Conversation

alexcrichton
Copy link
Member

Stabilize the std::prelude module by removing some of the less commonly used
functionality of it.

Rendered

Stabilize the `std::prelude` module by removing some of the less commonly used
functionality of it.
@alexcrichton
Copy link
Member Author

cc #497, an RFC specifically about Ordering, but reaching the same conclusion.

@SimonSapin
Copy link
Contributor

If user-defined preludes are allowed in some form, it is also unclear about how this would impact the inclusion of reexports in the standard library's prelude in some form.

Assuming that user-defined preludes need to be opted into, the syntax for that could be use my_prelude::*; and require no new language feature. Or am I missing something?

@aturon
Copy link
Member

aturon commented Dec 8, 2014

@SimonSapin

That doesn't quite give you the effect of the prelude, because it applies only to the current scope. There are some proposals in the works for allowing you to specify a custom prelude in your crate root that will be wholly imported into all scopes within the crate.

A feature like this would make it relatively easy to make "changes" to the std prelude without breakage by introducing separate versions, e.g. std::prelude::v1_2 (where the standard prelude would be std::prelude::v1_0).

@steveklabnik
Copy link
Member

I am 👍 for this.

// Rust code. Implementors of the `Ord` and `PartialOrd` traits will likely be
// required to import these names, but it is not expected that Rust code at
// large will require these names to be in the prelude.
pub use cmp::Ordering::{mod, Less, Equal, Greater};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mod

Is this a typo?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, it imports the Ordering enum, like cmp::{mod, Ordering} would import cmp and cmp::Ordering.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woah awesome, TIL

@kmcallister
Copy link
Contributor

// The prelude will be responsible for providing unicode-respecting methods on
// primitives while requiring that ascii-specific manipulation is imported
// manually.

I'm skeptical of providing Unicode-respecting methods in the prelude, because the operations are so complicated, with locale-dependence and many choices to make. It might be better to require the user to specify, via imports, which flavor of operations they're using.

There are a lot of formats (like HTTP and HTML) that use machine-interpreted text with ASCII-case-insensitive matching. This is a subtly different data type from "text written by humans for human consumption", but it's not worth forking &str and String. For this reason, you're just as likely to want ASCII ops as the (slow and complicated and locale-dependent) Unicode case folding. So I don't think either one should be in the prelude-imported extension traits.

@kmcallister
Copy link
Contributor

// While currently present in the prelude, these traits do not need to be in
// scope to use the language syntax associated with each trait. These traits are
// also only rarely used in bounds on generics and are consequently
// predominately used for `impl` blocks. Due to this lack of need to be included
// into all modules in Rust, these traits are all removed from the prelude.
...
pub use ops::{Deref, DerefMut};

Because of rust-lang/rust#15609, it is sometimes necessary to introduce an explicit deref_mut() call. Moving the trait out of the prelude will increase the effort to work around this bug. That said it's not a situation I run into a whole lot, and it would be better to just fix the bug :)

@SimonSapin
Copy link
Contributor

@kmcallister

For this reason, you're just as likely to want ASCII ops as the (slow and complicated and locale-dependent) Unicode case folding.

I disagree with "just as likely". You and I use ASCII-only case-insensitive matching routinely, but it’s fairly domain-specific: it only makes senses in a namespace like HTML element names where every "valid" name is ASCII, it’s just wrong on full Unicode text. It definitely should not be in the prelude.

As to Unicode case folding, some variations of it are locale-independent. Sure, they’re also wrong for the a few cases like the dotted/dotless iİıI in Turkish, but they’re much less wrong than ASCII-only. (SpecialCasing.txt doesn’t have that many language-sensitive mappings. CLDR might have more, but I haven’t figured out how that works yet.)

I think that some people will want to "just do XYZ" and not care about Unicode subtleties, much less being forced to specify a content language (which might just end up hard-coded to en-US). So we should give them a default, and it should be the "less wrong" one.

@alexcrichton
Copy link
Member Author

@kmcallister right now we are quite strict about str being UTF-8 at all times, and I think it may be odd if we don't offer basically any functionality on it by default due to worries about unicode. The functionality I'm thinking of are things like uppercase, lowercase, alphanuemrics, and whitespace detection to get functions like words(), is_alphanumeric, to_uppercase, etc. I definitely agree that unicode can be super complicated about this, but as @SimonSapin mentioned, almost everyone expects something of this form to work.

I expect we will very clearly document precisely what is_whitespace means (it's just doing a table lookup) and more flavorful functionality (like locale-specific mappings) can evolve in an external crate.

// will be removed from the prelude (and soon moved to std::sync as well).
//
// Additionally, while spawning a new thread is a common operation in concurrent
// programming, it is nota frequent operation in code in general. For example

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nota => not a

@alexcrichton
Copy link
Member Author

The discussion here seems to be slowing down, so I may try to look to merge this soon.

ping @kmcallister about unicode in the prelude
ping @aturon do you feel confident enough to propose std::prelude::v1 here?
cc @brson, @wycats (curious as to more thoughts)

@aturon
Copy link
Member

aturon commented Dec 14, 2014

@alexcrichton

@aturon do you feel confident enough to propose std::prelude::v1 here?

I think we should do it, yes (probably v1_0). It won't be visible unless you go looking for it, and it leaves space to add new prelude versions without them being part of the normal prelude glob import.

Broader context for others reading: we hope to eventually allow you to specify a custom prelude at the top of your crate (which would be glob imported everywhere, just as std::prelude normally is). This is useful both for non-std libraries providing preludes that work as nicely std::prelude, and to allow for breaking evolution of std::prelude in the future -- you could opt in to a new version.

If we don't introduce internal namespacing like this, there would not be a clear place for new prelude versions to go.

On the other hand, if we never end up evolving the prelude in this way, having v1_0 nested doesn't seem too harmful, given that you'd never write it in actual code.

@sfackler
Copy link
Member

I'm sitting on a proposal that should hopefully eliminate much of the need for third party preludes and the addition of anything to the libstd prelude, but sticking the current prelude in a v1_0 module seems pretty reasonable.

@aturon
Copy link
Member

aturon commented Dec 14, 2014

@sfackler Interesting! FWIW, the plan I had in mind was roughly to add a #[prelude] attribute that can be used at crate root on any item defining a module or bringing one into scope, e.g. #[prelude] use std::prelude::v1_2. If the attribute is used anywhere, the normal prelude is not injected; instead, the contents of all marked modules are glob imported into every namespace.

Curious to hear what you have in mind!

@sfackler
Copy link
Member

The tl;dr is to provide a way of marking a trait impl as always being in scope (e.g. inherent impl Foo for Bar). A significant portion of items in the current prelude are traits, and most of the utility of those reexports is not having the trait name in scope, but the methods defined on the trait. Many of those are basically never used as type bounds, like StrPrelude for example. Other traits like Iterator are used as trait bounds, but if they weren't in the prelude, they'd be imported for their methods far more often than they'd be imported for the name itself, if that makes sense.

In any case, it's a pretty clear post-1.0 improvement, so I'm not planning on writing it up formally until after the initial release.

@aturon
Copy link
Member

aturon commented Dec 14, 2014

@sfackler Ah ok, we've discussed that in the past. I don't think that completely covers what preludes offer, but it would certainly help!

@alexcrichton
Copy link
Member Author

I've pushed an update which recommends std::prelude::v1 containing the reexports instead of std::prelude (invisible change to all current users essentially).

@Gankra
Copy link
Contributor

Gankra commented Dec 19, 2014

Collections Reform v1 adds repeat to the prelude, which I think was never impl'd? Does this RFC officially override that decision? Note that v2's ergonomics partially assumed this would be something very easy to use (in deprecating certain Vec methods).

@aturon
Copy link
Member

aturon commented Dec 20, 2014

@gankro I think for the alpha, we're going to leave repeat and friends out; if this turns out to be a problem, we can add it back in for the beta.

@aturon
Copy link
Member

aturon commented Dec 20, 2014

While there has been surprisingly little discussion on this RFC thread, it's been brought up in the meeting and seen fairly widely in the community, and we need to move forward before the alpha. The core team has reviewed the RFC and is happy with the direction it's taking. We will also have an opportunity to tweak the exact contents before beta/1.0.

Tracking issue

@aturon aturon merged commit 30bb0f0 into rust-lang:master Dec 20, 2014
@Centril Centril added the A-prelude Proposals relating to the prelude. label Nov 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-prelude Proposals relating to the prelude.
Projects
None yet
Development

Successfully merging this pull request may close these issues.