Treat unit-like structs and variants like constant items in array repeat operands

This came up in a discussion on URLO:

Currently, array repeat operands treat unit-like structs and enum variants as normal expressions and not as paths to constant items.

This means that e.g.

struct Foo; // not Copy
const ARR: [Foo; 8] = [Foo; 8];

or

struct Foo; // not Copy
const ARR: [Option<Foo>; 8] = [None; 8];

do not compile with error E0277 ("the trait bound Foo: Copy is not satisfied") and instead you need to use a const block:

struct Foo; // not Copy
const ARR1: [Foo; 8] = [const { Foo }; 8];
const ARR2: [Option<Foo>; 8] = [const { None }; 8];

According to the Rust Reference in chapter 6.6

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.

and in chapter 6.7

Variant constructors are similar to struct definitions, and can be referenced by a path from the enumeration name, including in use declarations.

[…] Tuple-like and unit-like variants also define a constructor in the value namespace.

the constructors of unit-like structs and variants should behave as if a constant with the same name as the struct/variant was implicitly defined in the value namespace. But array repeat operands only treat paths to explicit constant items (and const block expressions) as constants.

This has the weird effect that

struct Foo; // not Copy
const ARR: [Foo; 8] = [Foo; 8];

fails to compile, but

struct Foo {} // still not Copy
const Foo: Foo = Foo {};

const ARR: [Foo; 8] = [Foo; 8];

compiles.

I think it would make sense to extend the definition of "constant item" for repeat operands to also include the implicit constants of unit-like structs and unit-like enum variants to make the language more consistent. Or could this cause any problems elsewhere?

1 Like
2 Likes

Note that you can work around this using a const block:

struct Foo; // not Copy
const ARR: [Foo; 8] = [const { Foo }; 8]; //works

Yes, I noted that in my post

and instead you need to use a const block

It's still weird that you need const { } for a unit-like struct or unit-like variant but not with a path to a constant item.

7 Likes