Specifically, allow use some::multipart::path as crate foo;
with semantics equivalent to extern crate some_multipart_path as foo;
if that path were a crate, even if it isn't. I.e. it behaves as a normal use
, but additionally (if defined in the root module namespace[1]) it makes the name also always available as ::foo
.
Why? Proc macros often need access to runtime libraries, and for attributes/derives, typically the best they can do is assume the relevant crates are available as ::cratename
. use as crate
would enable you to use derives/attributes exported from a wrapper crate without either the wrapper crate needing to create a copy of the macros using itself as the entry point or supplying a crate path to every invocation.
E.g. bevy uses and derives encase::ShaderType
for GPU "sharable" types. encase_derive
of course expects ::encase
to work, but bevy doesn't want their users to need to have a dependency on (a potentially different version of) encase, so bevy_encase_derive
exposes a copy of the same derive code (shared via encase_derive_impl
) which uses their pub use at bevy::render::render_resource::encase
instead[2]. If we had this feature, bevy could have users (potentially via macro) do use bevy::render::render_resource::encase as crate encase;
instead, and the normal derive would work. (Though they would probably still use the wrapped macro, to bypass the need for the use
, unless glob using a module with a pub
use as crate
would make ::name
available. But that seems almost certainly a bit too much.)
Yes, this can be abused to obfuscate and make ::name
not refer to a package, but I don't think the potential abuse avenues are any worse than the existing package renaming functionalities.
It could additionally permit just use some::path as crate;
inferring the name to use from the last path segment, but I don't think that's necessary and the explicitness is helpful here, since we're turning a multi segment name into a single segment name. Also, I chose to spell this as just as crate name
since there's nothing particularly extern
about using paths as crates, but it could also be spelled as extern crate name
.
For consistency, this would likely be permitted in nested use trees, but idiomatically always formatted into its own use statement.
That edition2018+ (path reform)
extern crate
only mounts to the extern prelude when written in the root module of the crate is at best surprising, and does makeextern crate
almost equivalent to just ause
when not at the crate root. I opened an issue to warn for this, because it's nonobvious behavior and can always be written clearer as a regularuse
.It might make sense to restrict
use as crate
to the crate root even ifextern crate
isn't, but I instead chose straight copying the semantics here. ↩︎Actually, bevy sniffs for your manifest, and will use any of
bevy::render::…
,bevy_render::…
, orencase
based on which it thinks is most likely to work. ↩︎