Skip to content

Cannot derrive Clone for empty enums when using no_std #31574

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

Closed
Roxxik opened this issue Feb 11, 2016 · 8 comments
Closed

Cannot derrive Clone for empty enums when using no_std #31574

Roxxik opened this issue Feb 11, 2016 · 8 comments
Labels
A-syntaxext Area: Syntax extensions

Comments

@Roxxik
Copy link

Roxxik commented Feb 11, 2016

derriving clone on an empty enum does not work without std, because it calls core::rt::begin_unwind:

#![no_std]

#[derive(Copy, Clone)]
enum MyEnum { }

leads to:

<anon>:4:16: 4:21 error: failed to resolve. Could not find `rt` in `core` [E0433]
<anon>:4 #[derive(Copy, Clone)]
                        ^~~~~
<anon>:4:16: 4:21 note: in this expansion of #[derive_Clone] (defined in <anon>)
<anon>:4:16: 4:21 help: see the detailed explanation for E0433
<anon>:4:16: 4:21 error: unresolved name `core::rt::begin_unwind` [E0425]
<anon>:4 #[derive(Copy, Clone)]
                        ^~~~~
<anon>:4:16: 4:21 note: in this expansion of #[derive_Clone] (defined in <anon>)
<anon>:4:16: 4:21 help: see the detailed explanation for E0425
error: main function not found
error: aborting due to 3 previous errors

Playground: https://play.rust-lang.org/?gist=7f786db03eca51a39900&version=nightly

@ticki
Copy link
Contributor

ticki commented Feb 11, 2016

Related: #29548

@durka
Copy link
Contributor

durka commented Feb 11, 2016

This is actually common to all derives, and the bug is that when generating a panic expression, it hardcodes std::rt::begin_unwind which gets automatically changed to core::rt::begin_unwind when #![no_std] is in effect. Perhaps it should generate a call to the actual panic!() macro instead? I'm not sure if macros can still be expanded at the point where this is generated.

@alexcrichton
Copy link
Member

Oh wow now that's just crazy (calling some runtime panic function..)

I think this would be more appropriate to perhaps derive as:

impl Clone for MyEnum {
    fn clone(&self) -> MyEnum {
        match *self {}
    }
}

@durka
Copy link
Contributor

durka commented Feb 11, 2016

@alexcrichton it could equivalently call intrinsics::unreachable() as it does in another part of the expansion... it does change the behavior of unsafe code (transmute::<_, MyEnum>(()).clone() triggers UB instead of panicking) but it's probably the right thing to do.

@alexcrichton
Copy link
Member

Perhaps, but using match *self {} has 0 dependencies on any API for any crate you're linking to, and should in general just be more robust

@durka
Copy link
Contributor

durka commented Feb 12, 2016

@alexcrichton as far as I can tell this is the only in-tree usage of syntax::ext::build::expr_unreachable and syntax::ext::build::expr_fail, and that's where the call to std/core::rt::begin_unwind is generated -- do you think it makes sense to change those functions (which are going to be broken on #![no_std] as in this issue), or leave them for dead and generate match *self {} from the #[derive] expander?

@alexcrichton
Copy link
Member

Hm, in theory we should just never call those functions. In contexts with empty enums they never exist so they shouldn't even panic, I'm not sure about others though.

@apasel422 apasel422 added the A-syntaxext Area: Syntax extensions label Feb 28, 2016
@bluss
Copy link
Member

bluss commented Feb 29, 2016

Generating match *self {} is simple and correct (it's safe Rust), but the same derive code is also used for n-ary match clauses, specifically for PartialEq and so on, where it generates match (&*self, &*rhs) { /* multiple cases */ } when there are more than 0 variants.

For that reason, changing it to use intrinsics unreachable may be the simplest. match (*self, *rhs) { /* empty */ } does not compile for void enums.

durka added a commit to durka/rust that referenced this issue Mar 10, 2016
durka added a commit to durka/rust that referenced this issue Mar 13, 2016
durka added a commit to durka/rust that referenced this issue Mar 14, 2016
bors added a commit that referenced this issue Mar 15, 2016
derive: use intrinsics::unreachable over unreachable!()

derive: use intrinsics::unreachable over unreachable!()

Fixes #31574.

Spawned from #32139.

r? @alexcrichton
durka added a commit to durka/rust that referenced this issue Apr 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-syntaxext Area: Syntax extensions
Projects
None yet
Development

No branches or pull requests

7 participants