-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add extern crate
items to extern prelude
#54658
Conversation
r? @cramertj (rust_highfive has picked a reviewer for you, use r? to override) |
cc @rust-lang/lang and @eddyb specifically |
1e4cd8d
to
5807971
Compare
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
r? @eddyb |
@@ -11,6 +11,8 @@ | |||
// run-pass | |||
// edition:2018 | |||
|
|||
extern crate core; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would want a dedicated test just for this I think a of copy this file with your change and one without.
cc @Nemo157 @japaric @ZackPierce re. the
This would actually almost be a way of building a custom prelude, or adding things to it at least. It does seem interesting; but if there is time we might want to fcp merge this. |
src/librustc_resolve/lib.rs
Outdated
if !attr::contains_name(&krate.attrs, "no_std") { | ||
extern_prelude.insert(Ident::from_str("std"), None); | ||
} else { | ||
extern_prelude.insert(Ident::from_str("core"), None); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really preferred having core
accessible even in non-no_std
builds. I think the rest of these changes, but with this still outside this else
gives the best pattern for crates with a std
feature:
#![cfg_attr(not(feature = "std"), no_std)]
use core::mem;
#[cfg(feature = "std")]
use std::boxed::Box;
You get the best of both worlds, minimal overhead compared to a normal std
using crate, plus compile-time checking that you don’t accidentally reference std
in a no_std
build (even when your target has std
available).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(If it’s possible there could be a warning about using core
if your crate has no cfg
-d out no_std
attribute to push people that aren’t using this pattern to use std
always, in case they copy-paste some core
using code)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using core
instead of std
where you don't have #![no_std]
is nothing bad we should lint against because it encourages keeping crates that much closer to working on #![no_std]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you that
use std::
should be possible when#![no_std]
is active.
This is the current nightly’s behaviour. I think this should not be possible, if it is ergonomic to do so. The only way to currently check whether you accidentally used std
is to setup a build for a target like thumbv6m-none-eabi
which doesn’t distribute a std
lib, this is a real pain point. I think with the 2018 module changes, and this one change to always have core
available (except no_core
), it becomes ergonomic enough to have #![no_std] use std::*;
be a hard error, and require crates to optionally enable no_std
when they want to use std
with a feature flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you that use std:: should be possible when #![no_std] is active.
I removed this bit when I realized it was wrong ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@petrochenkov Sorry; I don't follow what you are trying to say here...
I think the situation should be like so:
flag_std = true;
flag_core = true;
#![no_core] => [flag_core = false, #![no_std]]
#![no_std] => [flag_std = false]
flag_core => core is in the prelude.
flag_std => std is in the prelude.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Centril
That's exactly what I was trying to say.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@petrochenkov oh, ok, great :) let's do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... is it still the case this works?:
#![no_std]
use ::std::process::Command;
// -- Note the use of `::`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not unless you add extern crate std;
explicitly.
Starting with #54116 (the first point) absolute paths only look into crates listed in extern prelude, not crates lying around in library search directories.
Nominating for discussion on next meeting unless it is resolved before. |
I think the state after this PR can be summarized as a simple guideline:
(With cases being unspecify-able through |
👍 to this #54658 (comment) / thread of having |
@rfcbot poll Are we OK with this semantics for |
Team member @aturon has asked teams: T-lang, for consensus on:
|
@aturon I feel we should discuss this on the next meeting since it's not a trivial change; but I think I'm generally favorably inclined. |
☔ The latest upstream changes (presumably #54650) made this pull request unmergeable. Please resolve the merge conflicts. |
Question, @petrochenkov : how does this work with macro expansions? If a macro expansion generates an (cc @eddyb) |
This seems consistent with the intent of |
@rfcbot concern macro-expansion I'd like to understand how the macro-expansion interaction works before we do this. If it all "works fine", I have no objection. (See also this) |
⌛ Testing commit d1e337b with merge 8fb01908103f7dea32ce931c73987a3a597f2a02... |
💔 Test failed - status-appveyor |
@bors retry p=1 3 hour timeout again. |
Add `extern crate` items to extern prelude With this patch each `extern crate orig_name as name` item adds name `name` into the extern prelude, as if it was passed with `--extern`. What changes this causes in practice? Almost none! After all, `--extern` passed from Cargo was supposed to replace `extern crate` items in source, so if some code has `extern crate` item (or had it on 2015 edition), then it most likely uses `--extern` as well... ... with exception of a few important cases. - Crates using `proc_macro`. `proc_macro` is not passed with `--extern` right now and is therefore not in extern prelude. Together with 2018 edition import behavior this causes problems like #54418, e.g. ```rust extern crate proc_macro; use proc_macro::TokenStream; ``` doesn't work. It starts working after this patch. - `#[no_std]` crates using `std` conditionally, like @aturon described in #53166 (comment), and still wanting to write `std` instead of `crate::std`. This PR covers that case as well. This allows us to revert placing `std` into the extern prelude unconditionally, which was, I think, a [bad idea](#53166 (comment)). - Later `extern crate` syntax can be extended to support adding an alias to some local path to extern prelude, as it may be required for resolving #54647. Notes: - Only `extern crate` items from the root module added to the prelude, mostly because this behavior for items from inner modules would look very strange, rather than for technical reasons. This means you can opt out from the prelude additions with something like ```rust mod inner { pub(crate) extern crate foo; } use inner::foo; ``` - I haven't updated logic for 2018 import canaries to work fully correctly with this. The cases where it matters are pretty exotic (the `extern crate` item must be "sufficiently macro expanded") and I'd rather spend the time on eliminating the canaries entirely.
☀️ Test successful - status-appveyor, status-travis |
@petrochenkov @bors Are these changes already released in beta? I'm trying to build my proc macro, but I get this error:
|
@XX |
@petrochenkov rustc points here for the tracking issue for this feature, but this is a PR. Could you open an issue to track stabilization of this feature, and change rustc so point to that instead? |
@SimonSapin |
experiment: Support aliasing local crate root in extern prelude This PR provides some minimally invasive solution for the 2018 edition migration issue described in #54647 and affecting proc macro crates. `extern crate NAME as RENAME;` now accepts `NAME`=`self` and interprets it as referring to the local crate. As with other `extern crate` items, `RENAME` in this case gets into extern prelude in accordance with #54658, thus resolving #54647. ```rust extern crate self as serde; // Adds local crate to extern prelude as `serde` ``` This solution doesn't introduce any new syntax and has minimal maintenance cost, so it can be easily deprecated if something better is found in the future. Closes #54647
With this patch each
extern crate orig_name as name
item adds namename
into the extern prelude, as if it was passed with--extern
.What changes this causes in practice?
Almost none! After all,
--extern
passed from Cargo was supposed to replaceextern crate
items in source, so if some code hasextern crate
item (or had it on 2015 edition), then it most likely uses--extern
as well...... with exception of a few important cases.
Crates using
proc_macro
.proc_macro
is not passed with--extern
right now and is therefore not in extern prelude.Together with 2018 edition import behavior this causes problems like
use proc_macro
regressed from nightly-2018-09-14 to nightly 2018-09-15 in edition 2018 #54418, e.g.doesn't work.
It starts working after this patch.
#[no_std]
crates usingstd
conditionally, like @aturon described in std-using paths work just fine in 2018 edition #![no_std] #53166 (comment), and still wanting to writestd
instead ofcrate::std
. This PR covers that case as well.This allows us to revert placing
std
into the extern prelude unconditionally, which was, I think, a bad idea.Later
extern crate
syntax can be extended to support adding an alias to some local path to extern prelude, as it may be required for resolving Crates can't migrate to 2018 edition when they invoke coupled procedural macros #54647.Notes:
extern crate
items from the root module added to the prelude, mostly because this behavior for items from inner modules would look very strange, rather than for technical reasons.This means you can opt out from the prelude additions with something like
extern crate
item must be "sufficiently macro expanded") and I'd rather spend the time on eliminating the canaries entirely.