Idea: Compiler errors should suggest features which contain missing symbols

As a Rust newbie, I've spent a fair amount of time dealing with cryptic compiler errors due to missing features. It would be really nice if the compiler would emit an error with recovery suggestion pointing you to the missing feature.

I don't know much about how the compiler works, and I presume this may not be straightforward/possible if the compiler doesn't even parse files/functions/macros when the feature is missing. That said, at least Tokio manages to have a friendly reminder when you try to use an attribute macro and are missing the appropriate feature. In case there are places where suggesting the missing features could be done at little or no cost in compile time, I wanted to ask about it.

Anything under a #[cfg] is parsed (required to be syntactically valid) but nothing more. Notably, this means that if you #[cfg] out a mod, the compiler never even looks for/at the other source file, which might not even exist.

The compiler does sometimes do some light tracking of items which look like they're declared behind a #[cfg] for the purpose of error messages, but this is fairly limited and easy to accidentally "fool" by doing anything even slightly interesting, since the compiler only knows so little about #[cfg]d out code.

This is an unfortunate limitation of the "syntactic exclusion" form of conditional compilation. Strong exclusion is beneficial to compile time (don't need to analyze excluded code) and for "low level" cases where things literally don't exist on different target configurations, but it does limit how helpful the compiler can be when something "should" exist but doesn't.

The case with the attribute macro is a bit easier, because tokio can see the absence of the needed feature and generate a nice compile_error! when expanding the attribute at compile time.

TL;DR: there's effort to do this, but it's far from simple due to the conditional compilation model used by Rust.


One possibility that doesn't require changing how conditional compilation works, is to provide something like "non-cfg features". These would be features that don't utilize conditional compilation, instead using attributes to indicate certain items or modules are under a different path when certain features are enabled.

This wouldn't work with features that have dependencies attached, but it would have numerous applications within the standard library.

A limited version of this was implemented in 1.72, see Remember names of `cfg`-ed out items to mention them in diagnostics by Nilstrieb · Pull Request #109005 · rust-lang/rust · GitHub

This only helps when directly referencing the cfg-ed out item and does not help with trait impls.


Making this work with trait impls is basically impossible from what I can tell. With paths there are a few fortunate things that mean it's very cheap, but with trait impls (and also methods) you can't do it remotely reliably without doing a lot of analysis, defeating the point of cfg and also not working properly.