Motivation
There are some items that are usually imported by the name directly, such as AtomicUsize. And there are some types that are usually imported by module, e.g. atomic::Ordering, or mpsc::channel/mpsc::Sender. Editors are usually designed to autocomplete with the former method, which causes a bit of annoyance for items that are explicitly intended to be imported by module, resulting in unidiomatic code. Furthermore, these types often result in duplicate names, which look terrible on rustdoc output.
Proposal
Importable items can use an attribute like this:
#[well_known($import:path $(as $alias:ident)? $(, ::$usage:path)?)]
Using examples as above:
#[well_known(self, ::Ordering)] enum Ordering {...}
#[well_known(crate::sync::mpsc, ::channel)] fn channel() {...}
#[well_known(crate::result::Result::Ok, ::)]
$importis resolved at the item's module scope, where path aliases likecrate,superandselfare allowed. This tells the editor that we want to add an import for the item referenced by$import. Path arguments are not allowed in this path.$aliasis an alternative identifier that$importshould be aliased to. If not provided, it should be the last segment of$import.$usageis the path used to reference the actual item from the import. If omitted, this means$importalready resolves to the item.
If the #[well_known] attribute is not provided for a module-level item, the default is #[well_known(self::ItemIdent, ::)].
If the #[well_known] attribute is not provided for sub-module-level item (e.g. enum variants), it the default is #[well_known(self::ContainingType, ::ItemIdent)].
Compiler changes
When compiler reads a #[well_known] attribute, it validates that at the current scope, $import::$usage (or $import if $usage is omitted) resolves to the item that the attribute is applied to.
Lint changes
A new allowed-by-default lint well_known_paths is introduced. For each reference to item #[well_known(import as alias, ::usage)] item from some code under module user, if user is not equal to or a submodule of import (or the module containing import if it refers to an item), the lint is triggered if the reference is not in the form alias::usage, with a fix suggestion that changes the reference to alias::usage, and inserts use import as alias if missing.
Rust-analyzer changes
When autocomplete is executed for an item, instead of just importing the path into scope directly and autocomplete the item identifier, import alias::usage instead and add use import as alias if missing, similar to the lint behavior.
Rustdoc changes
When item is referenced from another module outside import in the signature (e.g. function inputs/outputs, type bounds, implementors), generate alias::usage as the text, instead of the current behavior of just using the identifier.
When item is linked by user documentation through intra-doc links in the form [path] (instead of [text](path)), use the well-known name instead of the path as provided by the user.
