Skip to content
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
Merged

Conversation

alexcrichton
Copy link
Member

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

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-api Relevant to the library API team, which will review and decide on the RFC. label Jun 30, 2015
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
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.

@Tobba
Copy link

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.

```

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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@Tobba
Copy link

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
Copy link
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.

@Ericson2314
Copy link
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.

@eddyb
Copy link
Member

eddyb commented Jul 1, 2015

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

@Tobba
Copy link

Tobba commented Jul 1, 2015

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


```rust
#[panic_fmt]
pub extern fn panic_fmt(msg: &core::fmt::Arguments) -> !;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member Author

@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
Copy link
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.

@eddyb
Copy link
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
Copy link
Contributor

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

@Ericson2314
Copy link
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.

@daboross
Copy link

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
Copy link
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
Copy link

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
Copy link
Member Author

@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
Copy link
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.

@aturon
Copy link
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 Aug 4, 2015
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 5, 2015
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
joelarmstrong added a commit to joelarmstrong/syscall.rs that referenced this pull request Aug 12, 2015
Broken on latest rust nightly because using no_std automatically injects
an "extern crate core". (rust-lang/rfcs#1184)
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
@Centril Centril added the A-no_std Proposals relating to #[no_std]. label Nov 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-no_std Proposals relating to #[no_std]. final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.