Suggested feature for a Rust edition -- stop suggesting both core:: and std:: to users

One common "papercut" I suffer from in rust is the compiler giving me the option of core:: or std::, without any guidance I can find anywhere official on what to pick.

For example, I just had the compiler ask me if I wanted core::fmt::Debug or std::fmt::Debug. The doc pages for these two are absolutely identical!

...
help: consider importing one of these items instead
1  | use core::fmt::Debug;
   |
1  | use std::fmt::Debug;

(perhaps unusually for an edition), I'm not suggesting a breaking change, but a change in "default suggested behaviour". In short, there is a "suggested" default to pick when an identical trait is in both core:: and std::, and the compiler uses this suggested default when producing warnings / errors.

Now, I'm not sure which one it should be (sorry!).

If the code is [no_std], it has to be the core:: one.

For normal code, I can see the argument for core:: (for consistency / future no_std), or std:: (so users don't need to worry about core). However, my main thought is, pick one and stop giving people confusing options (or, document the confusing option on core::fmt::Debug / std::fmt::Debug, and everywhere else this choice occurs).

11 Likes

I.e. every single type/trait in core... kinda intractable.

I think it's fair to call this a warning bug and fix it in all editions. For a type that's reexported in multiple locations, only one of them should be recommended. Probably the shorter path (by path segments) if it's reexported closer to the crate root, and the definition point of the paths are the same length.

Though I agree generally std should be recommended over core unless a crate has #![no_std], in which case core should be recommended. This can be a hardcoded special case since rustc knows about std and std knows about rustc. (Or maybe just a crate attribute.)

6 Likes

Maybe this is less serious than I thought (can just be a standard bug report, I tried looking for it but couldn't -- but it's hard to know exactly what to search for).

I did (informally) discuss this with some people, and there the impression I got was that suggesting one of std:: or core:: without the other was a "serious" change -- they may have just got too worked up.

This is also a problem with rustdoc search. By default, the search results on doc.rust-lang.org/std will include almost everything two or three times. It would be great to prune duplicates from the default “all crates” view, or at least move them to a separate list at the bottom.

(Again, it might be useful to have a special case for std to treat it as the “canonical” path for items it re-exports.)

7 Likes

Is this one of those things that could be fixed by a "unified" std, where instead of separate std/core/alloc crates there's just one std crate that uses normal features to turn the extras on/off? I know that topic has been discussed before, and one argument in favor of that is that I think it might help here, because then we could just always use/suggest std instead of alloc/core.

7 Likes

Yes, long-term when we merge std/alloc/core, this won't be an issue anymore.

In the meantime, though, this seems worth fixing, to make it easier for people to understand and act on the compiler's messages.

1 Like

Very much so. I've been considering putting together a pre-RFC to unify std/alloc/core, but it would obviously be a behemoth. It would likely be one of the single largest changes to stdlib ever (and would probably require a "pause" of sorts to take place to ensure no issues merging).

But this is tangential to the topic, so it's probably best to not discuss further in this thread.

1 Like

Plus, even if the "std hack" (to prefer std over core) is removed by unified std, preferring a canonical path is still useful for crates that expose the same item from multiple paths. I don't recall to what extent we currently prefer some paths over others, but there definitely are other crates in the exact same situation as std/core (e.g. rand_core vs rand, any other _core crate, and more).

4 Likes

There are already a few issues for this:

If someone wants to write up doc(canonical) (Feature request: `#[doc(canonical)]` · Issue #3011 · rust-lang/rfcs · GitHub) into a proper RFC, that would be extremely helpful.

3 Likes

That's news to me. Is there a discussion thread?

It has been spread out between many threads, some of Zulip and some here (I think).

As an outsider to those discussions the general idea is to have one crate (std) with features to toggle off parts of it. It seems like an excellent idea.

2 Likes

Does that mean the standard library has to be recompiled whenever a feature is enabled/disabled?

Given that we currently ship core, alloc, and std, it'd be very likely that the default rustup distribution would still ship with core, alloc, and std "feature profiles" precompiled. The main difference would be in how they're used, given that they're all "just std," and the benefits would mostly be in unifying all paths to ::std (moving forward), in enabling more customized -Zbuild-std profiles, and maybe in unlocking the mystical portability lint.

3 Likes

Another benefit would be the ability to have something like backtrace enabled in std while still having the Error trait in core, given that it would be the same trait, just feature gated.

(yes I am aware of ongoing work that doesn't require this)