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

RFC: Stabilize the #![no_std] attribute #1184

Merged
merged 6 commits into from Jul 30, 2015

Conversation

Projects
None yet
@alexcrichton
Member

alexcrichton commented Jun 30, 2015

Stabilize the #![no_std] attribute while also improving the ergonomics of
using libcore by default. Additionally add a new #![no_core] attribute to opt
out of linking to libcore.

rendered

RFC: Stabilize the #![no_std] attribute
Stabilize the `#![no_std]` attribute while also improving the ergonomics of
using libcore by default. Additionally add a new `#![no_core]` attribute to opt
out of linking to libcore. Finally, stabilize a number of language items
required by libcore which the standard library defines.

@alexcrichton alexcrichton self-assigned this Jun 30, 2015

@alexcrichton alexcrichton added the T-libs label Jun 30, 2015

Show outdated Hide outdated text/0000-stabilize-no_std.md
addition to the interface that it will be stabilized with. Each lang item will
no longer be defined with the `#[lang = "..."]` syntax but will instead receive
a dedicated attribute (e.g. `#[panic_fmt]`) to be attached to functions to
identify an implementation.

This comment has been minimized.

@eddyb

eddyb Jul 1, 2015

Member

These are already special-cased as "weak lang items" so using a mechanism different from regular lang items is not that much of a compromise IMO, but it would be nice if the existing situation was mentioned in the RFC.

@eddyb

eddyb Jul 1, 2015

Member

These are already special-cased as "weak lang items" so using a mechanism different from regular lang items is not that much of a compromise IMO, but it would be nice if the existing situation was mentioned in the RFC.

This comment has been minimized.

@nagisa

nagisa Jul 1, 2015

Contributor

Why?

I really like how current #[lang] works and that it is easy to grep for it, etc. I also believe it would be not too hard to stabilise #[lang="*"] only for certain *. That being said, I 👎 on this part of the RFC.

@nagisa

nagisa Jul 1, 2015

Contributor

Why?

I really like how current #[lang] works and that it is easy to grep for it, etc. I also believe it would be not too hard to stabilise #[lang="*"] only for certain *. That being said, I 👎 on this part of the RFC.

This comment has been minimized.

@eddyb

eddyb Jul 1, 2015

Member

They aren't really lang items, but rather a minimal set of compiler-sanctioned weak import/exports.
Libraries could be allowed to define custom "pluggable items" and then these 3 would not be known to the language, just libcore and its users.

@eddyb

eddyb Jul 1, 2015

Member

They aren't really lang items, but rather a minimal set of compiler-sanctioned weak import/exports.
Libraries could be allowed to define custom "pluggable items" and then these 3 would not be known to the language, just libcore and its users.

@Ericson2314

This comment has been minimized.

Show comment
Hide comment
@Ericson2314

Ericson2314 Jul 1, 2015

Contributor

Can we avoid stabilizing the lang items but do the rest? That will mean libcore is only stable to use when std is also linked, but I don't think that is a problem (for now). We still get the benefits of making the macros use core, and anybody actually writing kernel code will need unstable core features anyways.

There is a lot of jank in some those lang items as the RFC admits, and eh_personality is somewhat tied to libcompiler/libgcc. Also the fact that the undefined items problem in core and alloc are being defined in two different ways is worrysome---crate level "functors" a la the MLs that any library could use or define or instantiate would be better.

Contributor

Ericson2314 commented Jul 1, 2015

Can we avoid stabilizing the lang items but do the rest? That will mean libcore is only stable to use when std is also linked, but I don't think that is a problem (for now). We still get the benefits of making the macros use core, and anybody actually writing kernel code will need unstable core features anyways.

There is a lot of jank in some those lang items as the RFC admits, and eh_personality is somewhat tied to libcompiler/libgcc. Also the fact that the undefined items problem in core and alloc are being defined in two different ways is worrysome---crate level "functors" a la the MLs that any library could use or define or instantiate would be better.

@Tobba

This comment has been minimized.

Show comment
Hide comment
@Tobba

Tobba Jul 1, 2015

I propose that extern crate core; should be injected regardless of #![no_std]. This would make it easier to write #![no_std] libraries that contain macros which will work regardless of if the consumer crate is no_std or not.

Tobba commented Jul 1, 2015

I propose that extern crate core; should be injected regardless of #![no_std]. This would make it easier to write #![no_std] libraries that contain macros which will work regardless of if the consumer crate is no_std or not.

Show outdated Hide outdated text/0000-stabilize-no_std.md
```
This differs with the `panic_fmt` function today in that the file and line
number arguments are omitted. The libcore library will continue to provide

This comment has been minimized.

@Tobba

Tobba Jul 1, 2015

What's the rationale behind this change? This was convenient for formatting reasons, and I don't see why it should go.

@Tobba

Tobba Jul 1, 2015

What's the rationale behind this change? This was convenient for formatting reasons, and I don't see why it should go.

This comment has been minimized.

@alexcrichton

alexcrichton Jul 1, 2015

Member

We don't necessarily want to commit to providing a filename/line number in all panic messages as there have been musings in the past that a measurable overhead in terms of binary size and runtime is incurred from having all these strings/numbers in the binary.

@alexcrichton

alexcrichton Jul 1, 2015

Member

We don't necessarily want to commit to providing a filename/line number in all panic messages as there have been musings in the past that a measurable overhead in terms of binary size and runtime is incurred from having all these strings/numbers in the binary.

Show outdated Hide outdated text/0000-stabilize-no_std.md
instead of taking it by value, and the purpose of this is to ensure that the
function has a clearly defined ABI on all platforms in case that is required.
#### `eh_personality`

This comment has been minimized.

@Tobba

Tobba Jul 1, 2015

Both this and stack_exhausted seem like rather bad candidates for stabilization: they're both implementation details of the platform and compiler.

@Tobba

Tobba Jul 1, 2015

Both this and stack_exhausted seem like rather bad candidates for stabilization: they're both implementation details of the platform and compiler.

@Tobba

This comment has been minimized.

Show comment
Hide comment
@Tobba

Tobba Jul 1, 2015

Proposal: don't stabilize any lang items at all, due to the aforementioned arguments.

One of the current major problems of no_std is that writing libraries that work across both settings is very tedious - it currently involves maintaining a tangled mess of #[cfg] attributes which is rarely tested before release. Stabilizing lang items do nothing to improve this situation anyways.

Tobba commented Jul 1, 2015

Proposal: don't stabilize any lang items at all, due to the aforementioned arguments.

One of the current major problems of no_std is that writing libraries that work across both settings is very tedious - it currently involves maintaining a tangled mess of #[cfg] attributes which is rarely tested before release. Stabilizing lang items do nothing to improve this situation anyways.

@thepowersgang

This comment has been minimized.

Show comment
Hide comment
@thepowersgang

thepowersgang Jul 1, 2015

Contributor

I agree about not stabilizing any language items here, if this is just for allowing no_std library crates.

However - if stabilizing these language items will allow compilation of no_std binaries (using an externally defined entrypoint, instead of #[start]) then maybe.

Contributor

thepowersgang commented Jul 1, 2015

I agree about not stabilizing any language items here, if this is just for allowing no_std library crates.

However - if stabilizing these language items will allow compilation of no_std binaries (using an externally defined entrypoint, instead of #[start]) then maybe.

@Ericson2314

This comment has been minimized.

Show comment
Hide comment
@Ericson2314

Ericson2314 Jul 1, 2015

Contributor

Overall, I'm convinced over the long haul we can reduce the complexity of these implementation details (w.g.. with crate functors, stabilized rust without exceptions), so I rather leave them unstable as long as possible. Complexity is worse than instability for the foreseeable future.

Contributor

Ericson2314 commented Jul 1, 2015

Overall, I'm convinced over the long haul we can reduce the complexity of these implementation details (w.g.. with crate functors, stabilized rust without exceptions), so I rather leave them unstable as long as possible. Complexity is worse than instability for the foreseeable future.

@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb Jul 1, 2015

Member

@Tobba I thought $crate solved core/std selection issues in macros.

Member

eddyb commented Jul 1, 2015

@Tobba I thought $crate solved core/std selection issues in macros.

@Tobba

This comment has been minimized.

Show comment
Hide comment
@Tobba

Tobba Jul 1, 2015

@eddyb As far as I know it only works for referencing the current crate.

Tobba commented Jul 1, 2015

@eddyb As far as I know it only works for referencing the current crate.

Show outdated Hide outdated text/0000-stabilize-no_std.md
```rust
#[panic_fmt]
pub extern fn panic_fmt(msg: &core::fmt::Arguments) -> !;

This comment has been minimized.

@petrochenkov

petrochenkov Jul 1, 2015

Contributor

It doesn't feel right for me that functions deeply internal to Rust are stabilized as extern "C". Is anybody going to import them from C code? Do they need more ABI stability than any other functions?

@petrochenkov

petrochenkov Jul 1, 2015

Contributor

It doesn't feel right for me that functions deeply internal to Rust are stabilized as extern "C". Is anybody going to import them from C code? Do they need more ABI stability than any other functions?

This comment has been minimized.

@alexcrichton

alexcrichton Jul 1, 2015

Member

A possible extension one day could be to allow to define these kinds of lang items in other languages (e.g. C), so I figured it would be nice to have a defined ABI to leave the door open to that possibility.

@alexcrichton

alexcrichton Jul 1, 2015

Member

A possible extension one day could be to allow to define these kinds of lang items in other languages (e.g. C), so I figured it would be nice to have a defined ABI to leave the door open to that possibility.

Show outdated Hide outdated text/0000-stabilize-no_std.md
```rust
#[stack_exhausted]
pub extern fn stack_exhausted() -> !;

This comment has been minimized.

@nagisa

nagisa Jul 1, 2015

Contributor

This being a diverging function restricts

the implementation of what happens on stack overflow

to terminating the program. I don’t see how you could reallocate a bigger stack and return to normal execution. for example.

@nagisa

nagisa Jul 1, 2015

Contributor

This being a diverging function restricts

the implementation of what happens on stack overflow

to terminating the program. I don’t see how you could reallocate a bigger stack and return to normal execution. for example.

This comment has been minimized.

@eddyb

eddyb Jul 1, 2015

Member

That's not supported, our abuse of segmented stacks will be removed as soon as LLVM gets proper support for stack probes across all platforms.
IIRC there are some patches waiting to be reviewed and merged (cc @Zoxc).

@eddyb

eddyb Jul 1, 2015

Member

That's not supported, our abuse of segmented stacks will be removed as soon as LLVM gets proper support for stack probes across all platforms.
IIRC there are some patches waiting to be reviewed and merged (cc @Zoxc).

This comment has been minimized.

@nagisa

nagisa Jul 1, 2015

Contributor

our abuse of segmented stacks will be removed as soon as LLVM gets proper support for stack probes across all platforms.

Aware. What I’m just pointing out the function doesn’t exactly work as advertised just above it.

On Windows, where this abuse is not done, this “language item” is not used at all, so I’m doubtful this needs to be stabilised.

@nagisa

nagisa Jul 1, 2015

Contributor

our abuse of segmented stacks will be removed as soon as LLVM gets proper support for stack probes across all platforms.

Aware. What I’m just pointing out the function doesn’t exactly work as advertised just above it.

On Windows, where this abuse is not done, this “language item” is not used at all, so I’m doubtful this needs to be stabilised.

This comment has been minimized.

@alexcrichton

alexcrichton Jul 1, 2015

Member

I agree with @eddyb that there's really no way this function could ever return, adding segmented stacks back is likely to be a much more invasive change than just affecting this function.

@alexcrichton

alexcrichton Jul 1, 2015

Member

I agree with @eddyb that there's really no way this function could ever return, adding segmented stacks back is likely to be a much more invasive change than just affecting this function.

This comment has been minimized.

@huonw

huonw Jul 1, 2015

Member

We can presumably generalise the signature in future if we find use-cases for other ones.

@huonw

huonw Jul 1, 2015

Member

We can presumably generalise the signature in future if we find use-cases for other ones.

library. This means that users of `#![no_std]` will have to reimplement all of
this functionality themselves.
This RFC does not yet pave a way forward for using `#![no_std]` and producing an

This comment has been minimized.

@steveklabnik

steveklabnik Jul 1, 2015

Member

I would argue that it is paving a way forward, but it's just not there yet. These are the first steps.

@steveklabnik

steveklabnik Jul 1, 2015

Member

I would argue that it is paving a way forward, but it's just not there yet. These are the first steps.

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 1, 2015

Member

@Ericson2314, @Tobba, @thepowersgang

Can we avoid stabilizing the lang items but do the rest?

This is certainly an alternative! (which I have now added) The consequence of this decision is there will be no stable method of producing a staticlib or dylib which uses #![no_std] everywhere. I would personally like to enable this use case as having #![no_std] doesn't seem too useful without it. We can avoid stabilizing the exact signatures with the #![lang_items_abort] alternative mentioned, but there may be other ways to enable the use case of producing a final artifact without defining the precise signatures.


@Tobba

I propose that extern crate core; should be injected regardless of #![no_std].

Unfortunately I think this is not backwards compatible.

This would make it easier to write #![no_std] libraries that contain macros which will work regardless of if the consumer crate is no_std or not.

That's a good point, I've added a drawback to this RFC.

Member

alexcrichton commented Jul 1, 2015

@Ericson2314, @Tobba, @thepowersgang

Can we avoid stabilizing the lang items but do the rest?

This is certainly an alternative! (which I have now added) The consequence of this decision is there will be no stable method of producing a staticlib or dylib which uses #![no_std] everywhere. I would personally like to enable this use case as having #![no_std] doesn't seem too useful without it. We can avoid stabilizing the exact signatures with the #![lang_items_abort] alternative mentioned, but there may be other ways to enable the use case of producing a final artifact without defining the precise signatures.


@Tobba

I propose that extern crate core; should be injected regardless of #![no_std].

Unfortunately I think this is not backwards compatible.

This would make it easier to write #![no_std] libraries that contain macros which will work regardless of if the consumer crate is no_std or not.

That's a good point, I've added a drawback to this RFC.

@eefriedman

This comment has been minimized.

Show comment
Hide comment
@eefriedman

eefriedman Jul 2, 2015

Contributor

What's the point of stabilizing #![no_core]? It's not like it would actually be usable in stable Rust.

It makes zero sense to require users to provide an implementation of eh_personality. Assuming users don't do something weird, if you're not linking to libstd, there's no way to unwind, and therefore the eh_personality implementation will never be called. (Weird things here include manually calling _Unwind_RaiseException and unwinding through rust code by accident.)

A variant of the #[lang_items_abort] proposal: define an #[abort] attribute, as an alternative to all three lang-items. Say it has the signature fn abort(msg: &core::fmt::Arguments)->!, we call it whenever we hit any unrecoverable condition. It isn't allowed to unwind.

Contributor

eefriedman commented Jul 2, 2015

What's the point of stabilizing #![no_core]? It's not like it would actually be usable in stable Rust.

It makes zero sense to require users to provide an implementation of eh_personality. Assuming users don't do something weird, if you're not linking to libstd, there's no way to unwind, and therefore the eh_personality implementation will never be called. (Weird things here include manually calling _Unwind_RaiseException and unwinding through rust code by accident.)

A variant of the #[lang_items_abort] proposal: define an #[abort] attribute, as an alternative to all three lang-items. Say it has the signature fn abort(msg: &core::fmt::Arguments)->!, we call it whenever we hit any unrecoverable condition. It isn't allowed to unwind.

@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb Jul 2, 2015

Member

@eefriedman libcore can panic (and thus unwind), that's why this weak lang item contraption exists in the first place.

Member

eddyb commented Jul 2, 2015

@eefriedman libcore can panic (and thus unwind), that's why this weak lang item contraption exists in the first place.

@eefriedman

This comment has been minimized.

Show comment
Hide comment
@eefriedman

eefriedman Jul 2, 2015

Contributor

@eddyb libcore can panic, sure, but without libstd's implementation of panic_fmt, it isn't possible to actually unwind.

Contributor

eefriedman commented Jul 2, 2015

@eddyb libcore can panic, sure, but without libstd's implementation of panic_fmt, it isn't possible to actually unwind.

@Ericson2314

This comment has been minimized.

Show comment
Hide comment
@Ericson2314

Ericson2314 Jul 2, 2015

Contributor

@eefriedman As a practical matter, I think rustc demands eh_personality to generate pads assuming panic_fmt is defined to unwind. But certainly I agree this is not an ideal situation, and a great reason why even the existence of eh_personality, not just its signature, shouldn't be stabilized.

@alexcrichton

I would personally like to enable this use case as having #![no_std] doesn't seem too useful without it

Again, I don't think instability around Rust in the kernel is a problem, now or in the foreseeable future. Stabilizing #![no_std] and the existence of core to solve a particular problem like the macros is different, but now it is less clear whether doing so would help with that.

Contributor

Ericson2314 commented Jul 2, 2015

@eefriedman As a practical matter, I think rustc demands eh_personality to generate pads assuming panic_fmt is defined to unwind. But certainly I agree this is not an ideal situation, and a great reason why even the existence of eh_personality, not just its signature, shouldn't be stabilized.

@alexcrichton

I would personally like to enable this use case as having #![no_std] doesn't seem too useful without it

Again, I don't think instability around Rust in the kernel is a problem, now or in the foreseeable future. Stabilizing #![no_std] and the existence of core to solve a particular problem like the macros is different, but now it is less clear whether doing so would help with that.

@daboross

This comment has been minimized.

Show comment
Hide comment
@daboross

daboross Jul 4, 2015

#[no_std] makes sense as an attribute, it's fairly easy to tell what it's doing - #[no_core] however seems counterintuitive - it isn't exactly clear that it's also assuming #[no_std].

Would it make sense to just have one attribute, something like #[prelude()]? It would be used like #![prelude(core)] or #![prelude(none)], and #![prelude(std)] would be assumed if it isn't declared. believe it would make more sense to have using std, core, or no injected prelude all be under one attribute, rather than multiple.

daboross commented Jul 4, 2015

#[no_std] makes sense as an attribute, it's fairly easy to tell what it's doing - #[no_core] however seems counterintuitive - it isn't exactly clear that it's also assuming #[no_std].

Would it make sense to just have one attribute, something like #[prelude()]? It would be used like #![prelude(core)] or #![prelude(none)], and #![prelude(std)] would be assumed if it isn't declared. believe it would make more sense to have using std, core, or no injected prelude all be under one attribute, rather than multiple.

@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb Jul 4, 2015

Member

@daboross #![no_std] #[prelude] extern crate core; is actually what I expected the future direction to be.
Maybe we can still generalize prelude injection to custom and/or multiple crates.
That said, we also need to replace #[prelude_import]'s order-based glob priority with something proper, e.g. prelude glob imports can be overridden by glob imports which, in turn, can be overridden by explicit imports.

Member

eddyb commented Jul 4, 2015

@daboross #![no_std] #[prelude] extern crate core; is actually what I expected the future direction to be.
Maybe we can still generalize prelude injection to custom and/or multiple crates.
That said, we also need to replace #[prelude_import]'s order-based glob priority with something proper, e.g. prelude glob imports can be overridden by glob imports which, in turn, can be overridden by explicit imports.

@Virtlink

This comment has been minimized.

Show comment
Hide comment
@Virtlink

Virtlink Jul 7, 2015

All crates (including libstd) should be treated equally. There should be nothing that libstd can do that any other crate can't.

Firstly, I'd agree with @eddyb: introduce #[prelude] to manually use the prelude of the marked crate. This removes the special treatment of libstd's prelude. And we don't want to treat libcore's prelude special either, so let's not do #![no_core] and instead require #[prelude] extern crate core for users that want to use libcore and its prelude.

Then for at least eh_personality and stack_exhausted I'd add stub implementations that can be overridden by the user. Most users using #![no_std] don't need any special behavior here. However, overriding these stubs would be unstable, such that their signatures may change in the future. Libstd is just another crate overriding these stubs, and not special in that regard.

Finally, by default any Rust crate would implicitly include #[prelude] extern crate std; unless #![no_std] is specified. Then #![no_std] would mean no defaults instead of no libstd and prelude, which I think is more logical.

Virtlink commented Jul 7, 2015

All crates (including libstd) should be treated equally. There should be nothing that libstd can do that any other crate can't.

Firstly, I'd agree with @eddyb: introduce #[prelude] to manually use the prelude of the marked crate. This removes the special treatment of libstd's prelude. And we don't want to treat libcore's prelude special either, so let's not do #![no_core] and instead require #[prelude] extern crate core for users that want to use libcore and its prelude.

Then for at least eh_personality and stack_exhausted I'd add stub implementations that can be overridden by the user. Most users using #![no_std] don't need any special behavior here. However, overriding these stubs would be unstable, such that their signatures may change in the future. Libstd is just another crate overriding these stubs, and not special in that regard.

Finally, by default any Rust crate would implicitly include #[prelude] extern crate std; unless #![no_std] is specified. Then #![no_std] would mean no defaults instead of no libstd and prelude, which I think is more logical.

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 8, 2015

Member

@Virtlink

Firstly, I'd agree with @eddyb: introduce #[prelude] to manually use the prelude of the marked crate

The question about what to do with preludes is somewhat orthogonal to the #![no_std] story, there's a separate RFC for dealing with custom preludes.

let's not do #![no_core] and instead require #[prelude] extern crate core for users that want to use libcore and its prelude.

The problem with this is that Rust isn't very useful without extern crate core because of the lang items that it defines, and we ideally want the #![no_std] case to be just as ergonomic as the normal use case, and we wouldn't necessarily expect all users to write extern crate std;

Member

alexcrichton commented Jul 8, 2015

@Virtlink

Firstly, I'd agree with @eddyb: introduce #[prelude] to manually use the prelude of the marked crate

The question about what to do with preludes is somewhat orthogonal to the #![no_std] story, there's a separate RFC for dealing with custom preludes.

let's not do #![no_core] and instead require #[prelude] extern crate core for users that want to use libcore and its prelude.

The problem with this is that Rust isn't very useful without extern crate core because of the lang items that it defines, and we ideally want the #![no_std] case to be just as ergonomic as the normal use case, and we wouldn't necessarily expect all users to write extern crate std;

@Ericson2314

This comment has been minimized.

Show comment
Hide comment
@Ericson2314

Ericson2314 Jul 8, 2015

Contributor

My first priority is not stabilizing those lang items, but I'd prefer @eddyb's end goal too. Treating all crates as equally as possible an admirable goal, and one #[prelude] extern cate core; is but a tiny decrease in ergonomics.

In fact if we had proper glob-import priority like @eddyb requests, we could just do something like:

extern crate core;
use core::prelude_v1::*;

Even simpler!

Edit: proper glob-import priority, and crate-wide imports for exactly that.

Contributor

Ericson2314 commented Jul 8, 2015

My first priority is not stabilizing those lang items, but I'd prefer @eddyb's end goal too. Treating all crates as equally as possible an admirable goal, and one #[prelude] extern cate core; is but a tiny decrease in ergonomics.

In fact if we had proper glob-import priority like @eddyb requests, we could just do something like:

extern crate core;
use core::prelude_v1::*;

Even simpler!

Edit: proper glob-import priority, and crate-wide imports for exactly that.

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 8, 2015

Member

I believe the story of custom preludes or how we treat the prelude of core/std is firmly orthogonal to this PR. Whatever system we have for custom preludes will have some form of desugaring, but it's not related to #![no_std].

The #![no_std] attribute disables only the injection of std. This attribute instead switches the injection to be the core crate. The purpose of this is that #![no_std] is basically useless without extern crate core, so having it imply extern crate core seems quite useful.

What this means is that connecting #![no_std] and #![no_core] to prelude injection is a little bit of a red herring. You can think of the injection as the package "inject prelude and name" mechanism and these attributes are just switching what's injected.

Member

alexcrichton commented Jul 8, 2015

I believe the story of custom preludes or how we treat the prelude of core/std is firmly orthogonal to this PR. Whatever system we have for custom preludes will have some form of desugaring, but it's not related to #![no_std].

The #![no_std] attribute disables only the injection of std. This attribute instead switches the injection to be the core crate. The purpose of this is that #![no_std] is basically useless without extern crate core, so having it imply extern crate core seems quite useful.

What this means is that connecting #![no_std] and #![no_core] to prelude injection is a little bit of a red herring. You can think of the injection as the package "inject prelude and name" mechanism and these attributes are just switching what's injected.

@Ericson2314

This comment has been minimized.

Show comment
Hide comment
@Ericson2314

Ericson2314 Jul 8, 2015

Contributor

@alexcrichton While implicit extern crate and implicit #[prelude] are technically orthogonal, I don't see how #![no_std] still linking libcore is anything but a workaround the fact that we don't have a better prelude story. Do you think #[prelude] extern cate core; is sufficiently inconvenient to motivate adding another attribute #![no_core] to the language and treating libcore (more) specially?

Contributor

Ericson2314 commented Jul 8, 2015

@alexcrichton While implicit extern crate and implicit #[prelude] are technically orthogonal, I don't see how #![no_std] still linking libcore is anything but a workaround the fact that we don't have a better prelude story. Do you think #[prelude] extern cate core; is sufficiently inconvenient to motivate adding another attribute #![no_core] to the language and treating libcore (more) specially?

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 8, 2015

Member

@Ericson2314

Do you think #[prelude] extern cate core; is sufficiently inconvenient to motivate adding another attribute #![no_core] to the language and treating libcore (more) specially?

Yes

I've now updated this RFC to recommend #![lang_items_abort] as a crate attribute instead of stabilizing the lang items instead.

Member

alexcrichton commented Jul 8, 2015

@Ericson2314

Do you think #[prelude] extern cate core; is sufficiently inconvenient to motivate adding another attribute #![no_core] to the language and treating libcore (more) specially?

Yes

I've now updated this RFC to recommend #![lang_items_abort] as a crate attribute instead of stabilizing the lang items instead.

@Virtlink

This comment has been minimized.

Show comment
Hide comment
@Virtlink

Virtlink Jul 8, 2015

Alternatively, instead of trying to specify what we don't want to use (#![no_std], #![no_core]), might we specify what we do want to use? And if not specified, default to libstd.

Something like #![runtime(core)] if you want to use libcore, #![runtime(none)] if you want none of that, and #![runtime(std)] would be the implicit default. Such that if this is too inconvenient:

#![no_std]
#[prelude] extern crate core;

then surely this is nicely concise:

#![runtime(core)]

Virtlink commented Jul 8, 2015

Alternatively, instead of trying to specify what we don't want to use (#![no_std], #![no_core]), might we specify what we do want to use? And if not specified, default to libstd.

Something like #![runtime(core)] if you want to use libcore, #![runtime(none)] if you want none of that, and #![runtime(std)] would be the implicit default. Such that if this is too inconvenient:

#![no_std]
#[prelude] extern crate core;

then surely this is nicely concise:

#![runtime(core)]
@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 8, 2015

Member

@Virtlink yeah the precise name of the attribute is up for grabs, but I'd be somewhat wary of runtime(foo) as it looks like you can pass an arbitrary value in when in fact only three will suffice. I do think that having to write extern crate core is inconvenient as it's basically required by all Rust programs in existence so it doesn't make much sense to omit. It also establishes a clear convention with core being at the top of every #![no_std] crate of how items are idiomatically imported.

Member

alexcrichton commented Jul 8, 2015

@Virtlink yeah the precise name of the attribute is up for grabs, but I'd be somewhat wary of runtime(foo) as it looks like you can pass an arbitrary value in when in fact only three will suffice. I do think that having to write extern crate core is inconvenient as it's basically required by all Rust programs in existence so it doesn't make much sense to omit. It also establishes a clear convention with core being at the top of every #![no_std] crate of how items are idiomatically imported.

@Virtlink

This comment has been minimized.

Show comment
Hide comment
@Virtlink

Virtlink Jul 8, 2015

Indeed, it may look like #![runtime(foo)] accepts any arbitrary value, but that may not be that much of an issue. If a user ventures into no-std-land, I might hope they know what they're doing. On the other hand, an advantage of it is that, if ever, Rust ships with an alternative libstd's (e.g. for embedded devices with limited I/O and no threading), then you'd easily add another option #![runtime(embedded_std)]. It's extensible!

Virtlink commented Jul 8, 2015

Indeed, it may look like #![runtime(foo)] accepts any arbitrary value, but that may not be that much of an issue. If a user ventures into no-std-land, I might hope they know what they're doing. On the other hand, an advantage of it is that, if ever, Rust ships with an alternative libstd's (e.g. for embedded devices with limited I/O and no threading), then you'd easily add another option #![runtime(embedded_std)]. It's extensible!

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 8, 2015

Member

Today, however #![no_std] and #![no_core] are both extensible already, I don't think we want to invent too many ways to auto-inject a crate. For example we currently inject extern crate std into all Rust programs because requiring this annotation for every Rust program in existence is seen as too onerous. Similarly if you decide to opt out of std it's required for all those programs to link to core, so I believe it's too onerous to require that you actually declare you link to core.

I don't know why we would want to have another option for this runtime attribute, because at that level of customization it's not something we're expecting all Rust program in existence to have to worry about. That's the case where you just use extern crate and whatever custom prelude mechanism we have.

Member

alexcrichton commented Jul 8, 2015

Today, however #![no_std] and #![no_core] are both extensible already, I don't think we want to invent too many ways to auto-inject a crate. For example we currently inject extern crate std into all Rust programs because requiring this annotation for every Rust program in existence is seen as too onerous. Similarly if you decide to opt out of std it's required for all those programs to link to core, so I believe it's too onerous to require that you actually declare you link to core.

I don't know why we would want to have another option for this runtime attribute, because at that level of customization it's not something we're expecting all Rust program in existence to have to worry about. That's the case where you just use extern crate and whatever custom prelude mechanism we have.

@Virtlink

This comment has been minimized.

Show comment
Hide comment
@Virtlink

Virtlink Jul 8, 2015

Okay, imaginary future runtimes aside, there are just three options: libstd, libcore, and neither. With #![no_std] and #![no_core], there are four combinations, one of which doesn't make sense.

When encountering such a situation in my programs, I'd put those three options in an enum, which is what my #![runtime(core)] idea meant to illustrate.

Virtlink commented Jul 8, 2015

Okay, imaginary future runtimes aside, there are just three options: libstd, libcore, and neither. With #![no_std] and #![no_core], there are four combinations, one of which doesn't make sense.

When encountering such a situation in my programs, I'd put those three options in an enum, which is what my #![runtime(core)] idea meant to illustrate.

@Ericson2314

This comment has been minimized.

Show comment
Hide comment
@Ericson2314

Ericson2314 Jul 9, 2015

Contributor

I've now updated this RFC to recommend #![lang_items_abort] as a crate attribute instead of stabilizing the lang items instead.

Cool!

Yes

Well... I strongly disagree. But believing that does indeed make these topics orthogonal.

Another thing to keep in mind that affects both #![no_core] and #![runtime(???)] is that different environments use different subsets of the crates behind the facade. For example, core + alloc may be pretty standard for some applications. If/when things like libfs and libnet and made (the needs discussed in #185 are often still unaddressed), the practical subsets won't be identifiable by on unique library(e.g. core -> {core}, alloc -> {core, alloc}.

@eddyb's proposal is nice because then each library behind the facade can have its own prelude, and they can just be imported in any combination.

Contributor

Ericson2314 commented Jul 9, 2015

I've now updated this RFC to recommend #![lang_items_abort] as a crate attribute instead of stabilizing the lang items instead.

Cool!

Yes

Well... I strongly disagree. But believing that does indeed make these topics orthogonal.

Another thing to keep in mind that affects both #![no_core] and #![runtime(???)] is that different environments use different subsets of the crates behind the facade. For example, core + alloc may be pretty standard for some applications. If/when things like libfs and libnet and made (the needs discussed in #185 are often still unaddressed), the practical subsets won't be identifiable by on unique library(e.g. core -> {core}, alloc -> {core, alloc}.

@eddyb's proposal is nice because then each library behind the facade can have its own prelude, and they can just be imported in any combination.

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 29, 2015

Member

The libs team is in consensus to merge this RFC after the changes that I have just pushed up. This RFC no longer mentions stabilizing any lang items or the #![lang_items_abort] attribute, the only proposed changes are tweaking #![no_std] (without stabilizing it), adding #![no_core], and starting to consider the name "core" stable.

r? @aturon

Member

alexcrichton commented Jul 29, 2015

The libs team is in consensus to merge this RFC after the changes that I have just pushed up. This RFC no longer mentions stabilizing any lang items or the #![lang_items_abort] attribute, the only proposed changes are tweaking #![no_std] (without stabilizing it), adding #![no_core], and starting to consider the name "core" stable.

r? @aturon

@brson

This comment has been minimized.

Show comment
Hide comment
@brson

brson Jul 29, 2015

Contributor

I don't see any text or discussion about the impact on --test. Right now --test non-hygienically injects std paths. If no_std is stabilized and people try to build with --test this implementation detail will be exposed. I think the codegen for --test needs to be addressed as part of this RFC before no_std can happen.

Contributor

brson commented Jul 29, 2015

I don't see any text or discussion about the impact on --test. Right now --test non-hygienically injects std paths. If no_std is stabilized and people try to build with --test this implementation detail will be exposed. I think the codegen for --test needs to be addressed as part of this RFC before no_std can happen.

@brson

This comment has been minimized.

Show comment
Hide comment
@brson

brson Jul 29, 2015

Contributor

Hm, I guess this RFC isn't proposing to stabilize even no_std so it's not pressing.

Contributor

brson commented Jul 29, 2015

Hm, I guess this RFC isn't proposing to stabilize even no_std so it's not pressing.

@Virtlink

This comment has been minimized.

Show comment
Hide comment
@Virtlink

Virtlink Jul 29, 2015

Right now --test non-hygienically injects std paths.

I forgot about that. Unit tests depend on some stuff in libstd, so they need a libstd dependency. Adding the conditional libstd dependency (#[cfg(test)] extern crate std;) to a no_std crate that use a custom target breaks the test build. I believe the issue was that the libstd dependency in turn depends on its own libcore which conflicts with the libcore compiled for the custom target. Back then I made this issue for it.

Right now --test non-hygienically injects std paths.

I forgot about that. Unit tests depend on some stuff in libstd, so they need a libstd dependency. Adding the conditional libstd dependency (#[cfg(test)] extern crate std;) to a no_std crate that use a custom target breaks the test build. I believe the issue was that the libstd dependency in turn depends on its own libcore which conflicts with the libcore compiled for the custom target. Back then I made this issue for it.

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Jul 30, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184
@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 30, 2015

Member

@brson yeah this isn't stabilizing #![no_std] so it's not super pressing, but that module is largely because of the standard library itself. The test runner injects some ::std:: paths which means that testing a #![no_std] crate will need to have extern crate std at the top.

We can probably patch over this before actually stabilizing #![no_std]. There's a few things I can think of.

Member

alexcrichton commented Jul 30, 2015

@brson yeah this isn't stabilizing #![no_std] so it's not super pressing, but that module is largely because of the standard library itself. The test runner injects some ::std:: paths which means that testing a #![no_std] crate will need to have extern crate std at the top.

We can probably patch over this before actually stabilizing #![no_std]. There's a few things I can think of.

@aturon aturon merged commit c78deef into rust-lang:master Jul 30, 2015

@aturon

This comment has been minimized.

Show comment
Hide comment
@aturon

aturon Jul 30, 2015

Member

As @alexcrichton already mentioned, there was subteam consensus to merge this after scaling it back slightly (as per discussion with @dschatzberg and others).

Tracking issue

Member

aturon commented Jul 30, 2015

As @alexcrichton already mentioned, there was subteam consensus to merge this after scaling it back slightly (as per discussion with @dschatzberg and others).

Tracking issue

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Jul 30, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Jul 30, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Jul 30, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

bors added a commit to rust-lang/rust that referenced this pull request Jul 31, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Jul 31, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

bors added a commit to rust-lang/rust that referenced this pull request Jul 31, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Jul 31, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

bors added a commit to rust-lang/rust that referenced this pull request Jul 31, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

bors added a commit to rust-lang/rust that referenced this pull request Aug 1, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Aug 3, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Aug 3, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

bors added a commit to rust-lang/rust that referenced this pull request Aug 3, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

bors added a commit to rust-lang/rust that referenced this pull request Aug 4, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Aug 4, 2015

syntax: Implement #![no_core]
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

bors added a commit to rust-lang/rust that referenced this pull request Aug 4, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

bors added a commit to rust-lang/rust that referenced this pull request Aug 5, 2015

Auto merge of #27393 - alexcrichton:no-std-changes, r=brson
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.

[rfc]: rust-lang/rfcs#1184

Closes #27394

@thepowersgang thepowersgang referenced this pull request Aug 7, 2015

Closed

RFC: Custom preludes #890

joelarmstrong added a commit to joelarmstrong/syscall.rs that referenced this pull request Aug 12, 2015

fix "extern crate core" import
Broken on latest rust nightly because using no_std automatically injects
an "extern crate core". (rust-lang/rfcs#1184)

@posborne posborne referenced this pull request Aug 15, 2015

Closed

Failing to build example. #336

mokus0 added a commit to mokus0/rlibc that referenced this pull request Aug 16, 2015

mokus0 added a commit to mokus0/zinc that referenced this pull request Aug 16, 2015

Marwes added a commit to Marwes/mopa that referenced this pull request Jan 3, 2016

archaelus pushed a commit to archaelus/volatile_cell that referenced this pull request Oct 8, 2016

archaelus pushed a commit to archaelus/ioreg that referenced this pull request Oct 8, 2016

@nhynes nhynes referenced this pull request Jan 11, 2018

Closed

proc_macro and no_std #47342

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment