From aab8e13529cc558e0be48c57fda0e22b67b9be39 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 25 Feb 2019 18:31:37 -0500 Subject: [PATCH] add docs for zero bit types and pointers to zero bit types closes #1561 --- doc/langref.html.in | 55 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index b0c3a9e914..7c1a1a81d3 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1824,7 +1824,7 @@ fn foo(bytes: []u8) u32 { } {#code_end#} {#header_close#} - {#see_also|C Pointers#} + {#see_also|C Pointers|Pointers to Zero Bit Types#} {#header_close#} {#header_open|Slices#} @@ -4464,9 +4464,20 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { {#header_close#} {#header_close#} - {#header_open|void#} + {#header_open|Zero Bit Types#} +

For some types, {#link|@sizeOf#} is 0:

+

- {#syntax#}void{#endsyntax#} represents a type that has no value. Code that makes use of void values is + These types can only ever have one possible value, and thus + require 0 bits to represent. Code that makes use of these types is not included in the final generated code:

{#code_begin|syntax#} @@ -4476,8 +4487,8 @@ export fn entry() void { x = y; } {#code_end#} -

When this turns into LLVM IR, there is no code generated in the body of {#syntax#}entry{#endsyntax#}, - even in debug mode. For example, on x86_64:

+

When this turns into machine code, there is no code generated in the + body of {#syntax#}entry{#endsyntax#}, even in {#link|Debug#} mode. For example, on x86_64:

0000000000000010 <entry>:
   10:	55                   	push   %rbp
   11:	48 89 e5             	mov    %rsp,%rbp
@@ -4485,6 +4496,8 @@ export fn entry() void {
   15:	c3                   	retq   

These assembly instructions do not have any code associated with the void values - they only perform the function call prologue and epilog.

+ + {#header_open|void#}

{#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#} @@ -4556,6 +4569,38 @@ fn foo() i32 { {#code_end#} {#header_close#} + {#header_open|Pointers to Zero Bit Types#} +

Pointers to zero bit types also have zero bits. They always compare equal to each other:

+ {#code_begin|test#} +const std = @import("std"); +const assert = std.debug.assert; + +test "pointer to empty struct" { + const Empty = struct {}; + var a = Empty{}; + var b = Empty{}; + var ptr_a = &a; + var ptr_b = &b; + comptime assert(ptr_a == ptr_b); +} + {#code_end#} +

The type being pointed to can only ever be one value; therefore loads and stores are + never generated. {#link|ptrToInt#} and {#link|intToPtr#} are not allowed:

+ {#code_begin|test_err#} +const Empty = struct {}; + +test "@ptrToInt for pointer to zero bit type" { + var a = Empty{}; + _ = @ptrToInt(&a); +} + +test "@intToPtr for pointer to zero bit type" { + _ = @intToPtr(*Empty, 0x1); +} + {#code_end#} + {#header_close#} + {#header_close#} + {#header_open|comptime#}

Zig places importance on the concept of whether an expression is known at compile-time.