You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Crates can't migrate to 2018 edition when they invoke coupled procedural macros #54647
Procedural macros are often coupled with "runtime crates" which support the various macros that the procedural macro exports. These runtime crates, however, sometimes also want to invoke the procedural macro itself (think panic! and libstd, which exports it for users and also defines it itself).
Let's say our runtime crate is called foo. The macro today generally expands to paths that look like ::foo::MyType. This doesn't work by default in the crate foo itself, so foo typically includes a module that looks like:
mod foo {pubusesuper::*;}
And the enables the crate foo to use its own macros internally.
In the 2018 edition, however, the ::foo::MyType path unconditionally requires foo to be a crate, which isn't the case when we're compiling foo! As a result, these sorts of runtime crates don't have a great path forward when migrating to the 2018 edition.
@joshtriplett the procedural macro and the runtime support live in separate crates, think serde_derive vs serde. You would need some way to specify what crate $self would refer to, because in code generated by serde_derive all the types are defined by serde not serde_derive.
Perhaps even #![crate_name = "foo"] and --crate-name NAME can be re-purposed for that.
In general, if the crate knows its name (which is not always true), we can add that name into extern prelude.
EDIT: Nah, perhaps this need is too special, my_crate_name being generally available as an alias to crate in all crates built by Cargo would probably mostly cause confusion.
@eddyb
Do you mean extern crate foo?
If by side effect you mean that the extern prelude set becomes dynamic and can change in the process of expansion, then yes.
It's not so bad, it's the same thing as #[macro_use] extern crate ... adding names into the macro prelude, so it's trivially implementable in the existing infrastructure.
It breaks the uniform import path scheme with canaries though, so it's one more reason to move the implementation to the proper search in scope sooner (EDIT: or perhaps not and we'll just need more canaries?).
I think I found a problem with this workaround (even using Edition 2018): rustdoc examples. Since the error message is pretty poor I'm not certain, but I think it's using crate within the doc example.
Something I noticed in a 2018 edition crate using a 2015 crate/crate-derive pair, is that the trait needs to be used in the 2018 edition crate, while it wasn't necessary in 2015 code.
Something I noticed in a 2018 edition crate using a 2015 crate/crate-derive pair, is that the trait needs to be used in the 2018 edition crate, while it wasn't necessary in 2015 code.
That's expected. Derives were imported with #[macro_use] extern cratein 2015, whereas in 2018 they are imported the same way as any other name would be.
Is this going to be fixed before release or will these kinds of crates be incompatible across editions?
I don't know what the status of this is, but this issue doesn't refer to a crate being "incompatible across editions." That's not possible: there's no way to define a crate so that its "incompatible" with crates using a different edition. Crates using this pattern (which relies on an ambiguity in 2015 edition namespacing) just have to themselves continue to use the 2015 edition or one of the other workarounds discussed in this thread.
Activity
alexcrichton commentedon Sep 28, 2018
This was first reported at dtolnay/syn#507
eddyb commentedon Sep 28, 2018
cc @rust-lang/lang @petrochenkov
joshtriplett commentedon Sep 28, 2018
Shouldn't such macros use
$self::MyTypeor similar instead? (Does that not work for procedural macros, for some reason?)dtolnay commentedon Sep 28, 2018
@joshtriplett the procedural macro and the runtime support live in separate crates, think serde_derive vs serde. You would need some way to specify what crate
$selfwould refer to, because in code generated by serde_derive all the types are defined by serde not serde_derive.petrochenkov commentedon Sep 28, 2018
Hack: provide a version of macro with an extra argument for internal use and replace
::foowithcrateif it's used.petrochenkov commentedon Sep 28, 2018
Hack 2:
--extern foo=selfthat addsfoointo extern prelude as an alias tocrate.petrochenkov commentedon Sep 28, 2018
Or, in general, some way to add a name that's associated with the current crate into extern prelude.
joshtriplett commentedon Sep 28, 2018
@dtolnay Ah, I misunderstood the phrase "the crate foo to use its own macros internally".
petrochenkov commentedon Sep 28, 2018
Perhaps even
#![crate_name = "foo"]and--crate-name NAMEcan be re-purposed for that.In general, if the crate knows its name (which is not always true), we can add that name into extern prelude.
EDIT: Nah, perhaps this need is too special,
my_crate_namebeing generally available as an alias tocratein all crates built by Cargo would probably mostly cause confusion.petrochenkov commentedon Sep 28, 2018
extern crate foo = PATH;😄eddyb commentedon Sep 28, 2018
@petrochenkov wouldn't that create a bit of a "side-effect" in the system?
Or would you be required to place it in the root of another crate?
petrochenkov commentedon Sep 28, 2018
@eddyb
Do you mean
extern crate foo?If by side effect you mean that the extern prelude set becomes dynamic and can change in the process of expansion, then yes.
It's not so bad, it's the same thing as
#[macro_use] extern crate ...adding names into the macro prelude, so it's trivially implementable in the existing infrastructure.It breaks the uniform import path scheme with canaries though, so it's one more reason to move the implementation to the proper search in scope sooner (EDIT: or perhaps not and we'll just need more canaries?).
petrochenkov commentedon Sep 29, 2018
#54658 implements a possible prerequisite (extern crate items adding things into extern prelude).
6 remaining items
dhardy commentedon Oct 28, 2018
@stephaneyfx's solution seems to work nicely, but can be simplified:
Then just use
#cinsidequote!instead of$crate.Edit: I realise this will only work where the crate using the macro is using Edition 2018.
petrochenkov commentedon Oct 28, 2018
@dhardy
::crate::foowith leading::doesn't currently work (#53347), so there may be issues with disambiguated paths?dhardy commentedon Oct 30, 2018
I think I found a problem with this workaround (even using Edition 2018): rustdoc examples. Since the error message is pretty poor I'm not certain, but I think it's using
cratewithin the doc example.glandium commentedon Nov 23, 2018
Something I noticed in a 2018 edition crate using a 2015 crate/crate-derive pair, is that the trait needs to be
used in the 2018 edition crate, while it wasn't necessary in 2015 code.withoutboats commentedon Nov 27, 2018
That's expected. Derives were imported with
#[macro_use] extern cratein 2015, whereas in 2018 they are imported the same way as any other name would be.I don't know what the status of this is, but this issue doesn't refer to a crate being "incompatible across editions." That's not possible: there's no way to define a crate so that its "incompatible" with crates using a different edition. Crates using this pattern (which relies on an ambiguity in 2015 edition namespacing) just have to themselves continue to use the 2015 edition or one of the other workarounds discussed in this thread.
Auto merge of #55275 - petrochenkov:extself, r=eddyb
Disable stable builds (see rust-lang/rust#54647, fixed in Rust 1.34.0…
Alias the crate into the extern prelude.
Alias the crate into the extern prelude.