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, ::)]
-
$import
is resolved at the item's module scope, where path aliases likecrate
,super
andself
are 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. -
$alias
is an alternative identifier that$import
should be aliased to. If not provided, it should be the last segment of$import
. -
$usage
is the path used to reference the actual item from the import. If omitted, this means$import
already 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.