Skip to content

defining zero-sized structs #37

@nikomatsakis

Description

@nikomatsakis
Contributor

From #31:

"If you have a struct which -- transitively -- contains no data of non-zero size, then the size of that struct will be zero as well. These zero-sized structs appear frequently as exceptions in other layout considerations (e.g., single-field structs). An example of such a struct is std::marker::PhantomData."

Is that a sufficient definition for zero-sized structs? This seems like an important guarantee that we frequently rely upon for performance and other purposes, so it is worth specifying.

Activity

hanna-kruppe

hanna-kruppe commented on Oct 11, 2018

@hanna-kruppe

I'd rather spell out exactly the structural recursion that is going rather than hand wave it away with "transitively", but yes I think we should guarantee:

  • Arrays are ZSTs if the count is zero or the element type is ZST
  • A tuple is ZST if all elements are ZST
  • A struct is ZST if all fields are ZST
  • Empty enums are ZSTs

Enums are interesting because we could try to be smart around enums with a single variant but that will likely depend on the repr attribute which doesn't seem the case for structs (#[repr(C)] struct Foo {} is currently a ZST).

asajeffrey

asajeffrey commented on Oct 11, 2018

@asajeffrey

What about a one-case enum whose body is zero-sized, e.g.:

enum Foo { OnlyCase(SomethingZeroSized) }

or a union all of whose cases are zero-sized?

hanna-kruppe

hanna-kruppe commented on Oct 11, 2018

@hanna-kruppe

The only-variant-containing-ZST case could also be defined as ZST depending on repr attributes, but doesn't seem very useful.

Unions, good point, could probably be treated the same as structs, i.e., could be ZSTs even with repr(C).

rodrimati1992

rodrimati1992 commented on Oct 11, 2018

@rodrimati1992

Generic enums with 2 or more variants are zero-sized if every variant is Void except for a zero-sized variant.
https://play.rust-lang.org/?gist=0b3278bdd497b1bc3c9bccbb4ca828df&version=stable&mode=debug&edition=2015

Mark-Simulacrum

Mark-Simulacrum commented on Oct 11, 2018

@Mark-Simulacrum
Member

Empty enums are ZSTs

Aren't empty enums considered uninhabited? I'm not sure if those types are technically ZSTs since there's no actual valid representation.

hanna-kruppe

hanna-kruppe commented on Oct 11, 2018

@hanna-kruppe

@rodrimati1992 True, but I'd rather leave that sort of reasoning out of the picture for the initial step because:

@Mark-Simulacrum Empty enums are indeed uninhabited, but uninhabited types still have a size -- which is not necessarily zero, but definitely should be zero for empty enums.

RalfJung

RalfJung commented on Oct 11, 2018

@RalfJung
Member

Aren't empty enums considered uninhabited? I'm not sure if those types are technically ZSTs since there's no actual valid representation.

They are ZSTs in the sense that their size is 0 (layout.is_zst()). They are moreover uninhabited (layout.abi.is_uninhabited()). I think the latter currently implies the former, and that seems like a fairly reasonable axiom to me.

EDIT: Or maybe not, since we probably do consider (!, i32) to be uninhabited but cannot make it a ZST as @rkruppe reminded me.

nikomatsakis

nikomatsakis commented on Oct 23, 2018

@nikomatsakis
ContributorAuthor

I'd rather spell out exactly the structural recursion that is going rather than hand wave it away with "transitively", but yes I think we should guarantee:

This seems reasonable, except that it seems .. fine to say something stronger about enums (e.g., that an enum is zero-sized if it has only one "inhabited" variant and that variant is zero-sized). However, you are correct that we can "start small" (no pun intended) and grow, so perhaps we should just leave a "footnote" of some sort about that (in particular since I don't care to define inhabited just now).

nikomatsakis

nikomatsakis commented on Oct 23, 2018

@nikomatsakis
ContributorAuthor

It seems to me that the full text of this section ought to include notes about uninhabitedness and its connection to size as well.

nikomatsakis

nikomatsakis commented on Oct 23, 2018

@nikomatsakis
ContributorAuthor

I am wondering if we ought to pull "zero-sized types" into a section all its own, since it seems a bit .. cross-cutting?

added
C-open-questionCategory: An open question that we should revisit
and removed
C-open-questionCategory: An open question that we should revisit
on Nov 29, 2018

15 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-layoutTopic: Related to data structure layout (`#[repr]`)S-not-opsemDespite being in this repo, this is not primarily a T-opsem questionT-lang

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @nikomatsakis@RalfJung@asajeffrey@hanna-kruppe@Mark-Simulacrum

        Issue actions

          defining zero-sized structs · Issue #37 · rust-lang/unsafe-code-guidelines