`std::prelude::v2` with `TryFrom`/`TryInto` on edition 2021?

Can we add another module under std::prelude and auto-use it on edition 2021?

I remember when we tried to include those traits into prelude but figured out that it's a breaking change. But now we're close to new edition, and auto-use std::prelude::v1::*; is purely sugar added by the compiler.

One thing I can imagine that can be a problem is how we handle it on cargo fix. I don't have much idea on this part.

7 Likes

I would love to have a new prelude for a new edition, if that's possible. I can think of several other things that would be nice to include by default.

I was thinking std::prelude::v2021 or similar, but that's a minor point.

3 Likes

Maybe there could be a crate-level attribute like #![no_std] that chooses a version, e.g. #![prelude = v2], with an edition-based default. Then the easiest cargo fix is to just stay on the old prelude, though that's not very satisfying.

2 Likes

If we choose that route we don't need anything new. Just #![no_implicit_prelude] combined with use std::prelude::v1::*; would be enough. Though I'm still wondering if we can auto-migrate user code to use the v2 prelude.

1 Like

Explicit use would have to be repeated throughout the crate. My intent was to affect the implicit prelude.

2 Likes

While I'm in favor of adding these to a new prelude, I think that having the path be std::prelude::edition2021 or similar makes the most sense. 2015/2018 can of course be "aliased" by re-exporting everything from v1.

1 Like

There's also another possible solution: Add a preludes option to Cargo.toml.

preludes = ["std::prelude::v2"]

This would also allow adding custom preludes, such as diesel::prelude or crate::my_prelude.

Has this been proposed before?

2 Likes

I think files should remain self-contained; seeing use rayon::prelude::*; in the file makes the file self-contained, while specifying that in Cargo.toml requires looking in two places to understand the file, requires editing in two places, and allows the two to get separated or out of sync..

7 Likes

Yes, please! Adding TryFrom and TryInto everywhere is so annoying!

I'm not sure what criteria I'd want to use for judging who gets into the prelude, BUT it does seem like having From/Into in the prelude but not TryFrom/TryInto doesn't make much sense and misses a lot of the motivation for adding the Try* traits in the first place.

So I definitely think we should make a serious attempt to either prelude TryFrom/TryInto or unprelude From/Into. I'm guessing nobody wants to argue for the latter :slight_smile:

3 Likes

Stupid question: Is adding stuff to the prelude currently even considered a breaking change?

It's generally allowed without an edition. Unpin was added to the prelude recently, for example.

However, some things can't be added to the prelude without breaking a lot of user code. For example TryFrom::try_from conflicts with other trait methods named try_from, including ones in widely-used crates. In cases like this, it may be better to restrict the change to a new edition.

1 Like

With the prelude being implicit inside every module of a crate, it makes sense with a crate-level attribute. I'd want to avoid that different modules use different preludes, depending on use lines. On balance, this is not a flexibility I'd like to have, it makes code hard to read & write & understand.

I'd like an option to not have a prelude, whether or not more things get added to it.

That exists: #![no_std] or #![no_implicit_prelude]