Should types that contain zero-length vectors of themselves be allowed?
In the discussion of pull request #11839, which aims to check the representability of structs and enums properly in typeck, @huonw pointed out that the semantics for types that directly contain zero-length vectors of themselves are potentially still undecided.
If typeck allows enum Foo { A([Foo, .. 0]) } or
struct Bar { x: [Bar, .. 0] } then there is an infinite recursion + stack overflow in trans::adt::represent_type, so I will amend #11839 to disallow these cases and add a FIXME referencing this issue.
To me, it seems more consistent to allow any zero-length vector than to allow only some, but the only use case I can think of is that it may make some macros simpler to write.
In the discussion of pull request #11839, which aims to check the representability of structs and enums properly in
typeck, @huonw pointed out that the semantics for types that directly contain zero-length vectors of themselves are potentially still undecided.Consider for example (play):
struct Foo { recur: [Foo; 0], } fn main() { }If
typeckallowsenum Foo { A([Foo; 0]) }orstruct Bar { x: [Bar; 0] }then there is an infinite recursion + stack overflow intrans::adt::represent_type, so I will amend #11839 to disallow these cases and add a FIXME referencing this issue.To me, it seems more consistent to allow any zero-length vector than to allow only some, but the only use case I can think of is that it may make some macros simpler to write.
Felix S Klock II at 2019-03-22 15:17:42
Triage: the story here has not changed.
Jonathan Reem at 2014-12-15 08:25:02
triage: this is a question for @rust-lang/lang
Steve Klabnik at 2016-02-02 18:25:48
Currently we print the following. No discussion from lang team has happened to my knowledge. The error, at least, could be improved, since the recursive type T has zero size--not infinite size.
error[E0072]: recursive type `T` has infinite size --> test.rs:1:1 | 1 | struct T([T; 0]); | ^^^^^^^^^^^^^^^^^ recursive type has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `T` representable error: aborting due to previous errorMark Rousskov at 2017-04-28 01:48:08
I'm inclined to consider this a bug. We should check specifically for vectors that we can prove to be of zero-size.
Niko Matsakis at 2017-04-28 18:55:56
The systems in question are under active rewrite by @eddyb -- but this seems like potentially a good candidate for mentorship. I think that supporting the examples given here would be relatively straight-forward.
Niko Matsakis at 2017-04-28 18:56:51
[T; 0]has the alignment ofTand if there are a few types in the cycle, they should all getT's alignment, which may depend on other types in the cycle, so it's not that simple. That said, it's plausible computing type alignment can be done separately from size/layout.Eduard-Mihai Burtescu at 2017-04-28 19:47:54
This compiles without error today. Marking as E-needstest.
Mark Rousskov at 2018-07-28 21:55:17
Wait, how?
[T; 0]still needsT's alignment. Are you sure the type's layout is ever computed? That is, are you using the type at all?Eduard-Mihai Burtescu at 2018-07-29 06:23:54
Oh I confused myself and read the example above as a
Foo<T>([T; 0])and instantiated it with u32 which obviously does work. Unmarking.Mark Rousskov at 2018-07-29 14:52:42
I'd like to suggest that this should be allowed, for composition with const generics:
#![feature(const_generics)] struct X<const L: usize> { foo: u8, bar: [X<0>;L], }If others agree I'd also be interested in working on the relevant changes.
snek at 2020-04-27 21:15:56
I have a use-case for this for a small-vec-like type which needs to use
[T; 0]for proper alignment of the wrapper struct, but currently this prevents such type from being used in recursive types.struct InlineArray<T> { align: [T; 0], ... // inline or out-of-line storage } enum Recursive { A(InlineArray<Recursive>), B, }Kornel at 2021-02-16 15:43:48