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

Constants in array repeat expression feature doesn't work with unit structs #80890

Closed
rodrimati1992 opened this issue Jan 10, 2021 · 7 comments
Closed
Labels
C-bug Category: This is a bug.

Comments

@rodrimati1992
Copy link
Contributor

rodrimati1992 commented Jan 10, 2021

I tried this code:

#[derive(Debug)]
struct Foo;

fn main(){
    let repeated = [Foo; 4];
    println!("{:?}", repeated);
}

I expected to the code to compile without errors, since Foo is a constant and constants in array repeat expression is stable

Instead, this happened: the code doesn't compile, saying that Foo isn't Copy

error[E0277]: the trait bound `Foo: Copy` is not satisfied
 --> src/main.rs:5:20
  |
5 |     let repeated = [Foo; 4];
  |                    ^^^^^^^^ the trait `Copy` is not implemented for `Foo`
  |

Unit structs are described as creating a constant of the same name in the reference:
https://doc.rust-lang.org/nightly/reference/items/structs.html

A unit-like struct is a struct without any fields, defined by leaving off the list of fields entirely. Such a struct implicitly defines a constant of its type with the same name.

Meta

rustc --version --verbose:

1.51.0-nightly (2021-01-09 6184f23950fb4aa14884)

Workarounds

Defining the Foo constant explicitly does compile:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=675dd9fdcc63bde83dfb33a5f0e19054

#[derive(Debug)]
struct Foo{}

const Foo: Foo = Foo{};

fn main(){
    let repeated = [Foo; 4];
    println!("{:?}", repeated);
}
@rodrimati1992 rodrimati1992 added the C-bug Category: This is a bug. label Jan 10, 2021
@rodrimati1992 rodrimati1992 changed the title Constants in array repeat expression doesn't work with unit structs Constants in array repeat expression feature doesn't work with unit structs Jan 10, 2021
@fmease
Copy link
Member

fmease commented Jan 10, 2021

This issue will be solved with const-in-array-repeat-expressions #49147 or alternatively partially addressed with inline consts #76001. So this issue should be closed.

Right now, your code does not compile since you did not specify #![feature(const_in_array_repeat_expressions)].

@rodrimati1992
Copy link
Contributor Author

rodrimati1992 commented Jan 10, 2021

This pull request acknowledges that constants in array repeat expressions are already stable, which is how I was able to make this work with the explicit const.

@fmease
Copy link
Member

fmease commented Jan 10, 2021

Only a small subset:

However, I propose we instead just officially accept this and stabilize a small subset of RFC 2203

@rodrimati1992
Copy link
Contributor Author

I'm saying is that this is part of the stabilized subset:

#[derive(Debug)]
struct Foo{}

const Foo: Foo = Foo{};

fn main(){
    let repeated = [Foo; 4];
    println!("{:?}", repeated);
}

so this should also work:

#[derive(Debug)]
struct Foo;

fn main(){
    let repeated = [Foo; 4];
    println!("{:?}", repeated);
}

I fail to see how they're not exactly equivalent.

@fmease
Copy link
Member

fmease commented Jan 10, 2021

I'm saying is that this is part of the stabilized subset:

As far as I am aware, it is not. Read the pull request again but carefully. I don't intend to sound rude but the subset solely contains the syntactic class of paths to constants defined by a const item. Foo is not defined as a const. Yes, it is a constant but that is not what was accidentally stabilized.

@ThatsNoMoon
Copy link

This seems like an appropriate and correct explanation for why this happens, but not an appropriate justification. This should work, in my opinion. Is there some argument against this just working as is? In the RFC it seems clear that it was decided that it's acceptable for this subset to be stable anyway, and this makes the stable subset more confusing. From a user's perspective, these cases are not different and undocumented compiler internal distinctions seem immaterial to whether this behavior should exist.

@KamilaBorowska
Copy link
Contributor

KamilaBorowska commented Feb 8, 2021

The difference is that the case with a constant was accidentally stabilized since 1.38, this wasn't. It was figured that using a const is fine to stabilize as it doesn't depend on implicit promotion. At this point it's better to reduce implicit promotion to minimum, in this case specifically to the subset that was accidentally stabilized before to leave room for tweaking the rules if necessary.

Will unit structs be allowed in the future in this position? This is very likely, but there is no need to decide on stabilization of that right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

5 participants