diff --git a/README.md b/README.md index d5199a1fa8..d4475fcf81 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![ZIG](https://ziglang.org/zig-logo.svg) -A general-purpose programming language designed for **robustness**, -**optimality**, and **maintainability**. +A general-purpose programming language for maintaining **robust**, **optimal**, +and **reusable** code. ## Resources diff --git a/build.zig b/build.zig index ca78bdf197..cd25001eef 100644 --- a/build.zig +++ b/build.zig @@ -155,7 +155,7 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void { ) catch unreachable; for (dep.system_libs.toSliceConst()) |lib| { const static_bare_name = if (mem.eql(u8, lib, "curses")) - ([]const u8)("libncurses.a") + @as([]const u8, "libncurses.a") else b.fmt("lib{}.a", lib); const static_lib_name = fs.path.join( diff --git a/ci/azure/pipelines.yml b/ci/azure/pipelines.yml index d2cd30cc7c..5dbfe5a338 100644 --- a/ci/azure/pipelines.yml +++ b/ci/azure/pipelines.yml @@ -14,7 +14,7 @@ jobs: displayName: 'Build and test' - job: BuildLinux pool: - vmImage: 'ubuntu-16.04' + vmImage: 'ubuntu-18.04' timeoutInMinutes: 360 @@ -53,7 +53,7 @@ jobs: strategy: maxParallel: 1 pool: - vmImage: 'ubuntu-16.04' + vmImage: 'ubuntu-18.04' variables: version: $[ dependencies.BuildLinux.outputs['main.version'] ] steps: diff --git a/ci/drone/drone.yml b/ci/drone/drone.yml index 474f5b6d09..8fff358a93 100644 --- a/ci/drone/drone.yml +++ b/ci/drone/drone.yml @@ -9,6 +9,8 @@ steps: - name: build-and-test image: ziglang/static-base:llvm9-1 environment: + SRHT_OAUTH_TOKEN: + from_secret: SRHT_OAUTH_TOKEN AWS_ACCESS_KEY_ID: from_secret: AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY: diff --git a/doc/docgen.zig b/doc/docgen.zig index 07a7f23968..502ffda784 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -10,8 +10,8 @@ const testing = std.testing; const max_doc_file_size = 10 * 1024 * 1024; -const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt(); -const obj_ext = std.build.Target(std.build.Target.Native).oFileExt(); +const exe_ext = @as(std.build.Target, std.build.Target.Native).exeFileExt(); +const obj_ext = @as(std.build.Target, std.build.Target.Native).oFileExt(); const tmp_dir_name = "docgen_tmp"; const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext; @@ -856,6 +856,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok .LineComment, .DocComment, + .ContainerDocComment, .ShebangLine, => { try out.write(""); diff --git a/doc/langref.html.in b/doc/langref.html.in index 3eb30c3058..5ecf312044 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -164,15 +164,17 @@
{#header_open|Introduction#}

- Zig is a general-purpose programming language designed for robustness, - optimality, and maintainability. + Zig is a general-purpose programming language for maintaining robust, + optimal, and reusable code.

Often the most efficient way to learn something new is to see examples, so @@ -202,11 +204,8 @@ const std = @import("std"); pub fn main() !void { - // If this program is run without stdout attached, exit with an error. - const stdout_file = try std.io.getStdOut(); - // If this program encounters pipe failure when printing to stdout, exit - // with an error. - try stdout_file.write("Hello, world!\n"); + const stdout = &std.io.getStdOut().outStream().stream; + try stdout.print("Hello, {}!\n", "world"); } {#code_end#}

@@ -712,7 +711,7 @@ test "init with undefined" { } {#code_end#}

- {#syntax#}undefined{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to any type. + {#syntax#}undefined{#endsyntax#} can be {#link|coerced|Type Coercion#} to any type. Once this happens, it is no longer possible to detect that the value is {#syntax#}undefined{#endsyntax#}. {#syntax#}undefined{#endsyntax#} means the value could be anything, even something that is nonsense according to the type. Translated into English, {#syntax#}undefined{#endsyntax#} means "Not a meaningful @@ -920,7 +919,7 @@ fn divide(a: i32, b: i32) i32 { {#syntax#}f128{#endsyntax#}.

- Float literals {#link|implicitly cast|Implicit Casts#} to any floating point type, + Float literals {#link|coerce|Type Coercion#} to any floating point type, and to any {#link|integer|Integers#} type when there is no fractional component.

{#code_begin|syntax#} @@ -950,7 +949,7 @@ const nan = std.math.nan(f128); {#code_begin|obj|foo#} {#code_release_fast#} const builtin = @import("builtin"); -const big = f64(1 << 40); +const big = @as(f64, 1 << 40); export fn foo_strict(x: f64) f64 { return x + big - big; @@ -1652,7 +1651,7 @@ test "iterate over an array" { for (message) |byte| { sum += byte; } - assert(sum == usize('h') + usize('e') + usize('l') * 2 + usize('o')); + assert(sum == 'h' + 'e' + 'l' * 2 + 'o'); } // modifiable array @@ -1734,6 +1733,43 @@ test "array initialization with function calls" { {#code_end#} {#see_also|for|Slices#} + {#header_open|Anonymous List Literals#} +

Similar to {#link|Enum Literals#} and {#link|Anonymous Struct Literals#} + the type can be omitted from array literals:

+ {#code_begin|test|anon_list#} +const std = @import("std"); +const assert = std.debug.assert; + +test "anonymous list literal syntax" { + var array: [4]u8 = .{11, 22, 33, 44}; + assert(array[0] == 11); + assert(array[1] == 22); + assert(array[2] == 33); + assert(array[3] == 44); +} + {#code_end#} +

+ If there is no type in the result location then an anonymous list literal actually + turns into a {#link|struct#} with numbered field names: +

+ {#code_begin|test|infer_list_literal#} +const std = @import("std"); +const assert = std.debug.assert; + +test "fully anonymous list literal" { + dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"}); +} + +fn dump(args: var) void { + assert(args.@"0" == 1234); + assert(args.@"1" == 12.34); + assert(args.@"2"); + assert(args.@"3"[0] == 'h'); + assert(args.@"3"[1] == 'i'); +} + {#code_end#} + {#header_close#} + {#header_open|Multidimensional Arrays#}

Mutlidimensional arrays can be created by nesting arrays: @@ -2003,7 +2039,7 @@ test "variable alignment" { } } {#code_end#} -

In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to a +

In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|coerced|Type Coercion#} to a {#syntax#}*const i32{#endsyntax#}, a pointer with a larger alignment can be implicitly cast to a pointer with a smaller alignment, but not vice versa.

@@ -2019,7 +2055,7 @@ var foo: u8 align(4) = 100; test "global variable alignment" { assert(@typeOf(&foo).alignment == 4); assert(@typeOf(&foo) == *align(4) u8); - const slice = (*[1]u8)(&foo)[0..]; + const slice = @as(*[1]u8, &foo)[0..]; assert(@typeOf(slice) == []align(4) u8); } @@ -2114,7 +2150,7 @@ const fmt = @import("std").fmt; test "using slices for strings" { // Zig has no concept of strings. String literals are arrays of u8, and // in general the string type is []u8 (slice of u8). - // Here we implicitly cast [5]u8 to []const u8 + // Here we coerce [5]u8 to []const u8 const hello: []const u8 = "hello"; const world: []const u8 = "世界"; @@ -2526,7 +2562,8 @@ test "overaligned pointer to packed struct" { Don't worry, there will be a good solution for this use case in zig.

{#header_close#} - {#header_open|struct Naming#} + + {#header_open|Struct Naming#}

Since all structs are anonymous, Zig infers the type name based on a few rules.

- This kind of type resolution chooses a type that all peer types can implicitly cast into. Here are + This kind of type resolution chooses a type that all peer types can coerce into. Here are some examples:

{#code_begin|test#} @@ -5007,8 +5117,8 @@ test "peer resolve array and const slice" { comptime testPeerResolveArrayConstSlice(true); } fn testPeerResolveArrayConstSlice(b: bool) void { - const value1 = if (b) "aoeu" else ([]const u8)("zz"); - const value2 = if (b) ([]const u8)("zz") else "aoeu"; + const value1 = if (b) "aoeu" else @as([]const u8, "zz"); + const value2 = if (b) @as([]const u8, "zz") else "aoeu"; assert(mem.eql(u8, value1, "aoeu")); assert(mem.eql(u8, value2, "zz")); } @@ -5023,10 +5133,10 @@ test "peer type resolution: ?T and T" { } fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { if (c) { - return if (b) null else usize(0); + return if (b) null else @as(usize, 0); } - return usize(3); + return @as(usize, 3); } test "peer type resolution: [0]u8 and []const u8" { @@ -5293,7 +5403,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {

For example, if we were to introduce another function to the above snippet:

- {#code_begin|test_err|cannot store runtime value in type 'type'#} + {#code_begin|test_err|values of type 'type' must be comptime known#} fn max(comptime T: type, a: T, b: T) T { return if (a > b) a else b; } @@ -5815,7 +5925,7 @@ test "printf too many arguments" {

Zig doesn't care whether the format argument is a string literal, - only that it is a compile-time known value that is implicitly castable to a {#syntax#}[]const u8{#endsyntax#}: + only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}:

{#code_begin|exe|printf#} const warn = @import("std").debug.warn; @@ -6185,7 +6295,7 @@ fn func() void {

{#syntax#}await{#endsyntax#} is a suspend point, and takes as an operand anything that - implicitly casts to {#syntax#}anyframe->T{#endsyntax#}. + coerces to {#syntax#}anyframe->T{#endsyntax#}.

There is a common misconception that {#syntax#}await{#endsyntax#} resumes the target function. @@ -6445,6 +6555,14 @@ comptime {

{#header_close#} + {#header_open|@as#} +
{#syntax#}@as(comptime T: type, expression) T{#endsyntax#}
+

+ Performs {#link|Type Coercion#}. This cast is allowed when the conversion is unambiguous and safe, + and is the preferred way to convert between types, whenever possible. +

+ {#header_close#} + {#header_open|@asyncCall#}
{#syntax#}@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: ...) anyframe->T{#endsyntax#}

@@ -6493,14 +6611,14 @@ async fn func(y: *i32) void { This builtin function atomically dereferences a pointer and returns the value.

- {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, - or an integer whose bit count meets these requirements: + {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#} + an integer whose bit count meets these requirements:

+ or an enum with a valid integer tag type.

TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe we can remove this restriction @@ -6541,6 +6659,25 @@ async fn func(y: *i32) void {

  • {#syntax#}.Min{#endsyntax#} - stores the operand if it is smaller. Supports integers and floats.
  • {#header_close#} + {#header_open|@atomicStore#} +
    {#syntax#}@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: builtin.AtomicOrder) void{#endsyntax#}
    +

    + This builtin function atomically stores a value. +

    +

    + {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#} + an integer whose bit count meets these requirements: +

    + or an enum with a valid integer tag type. +

    + TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe + we can remove this restriction +

    + {#header_close#} {#header_open|@bitCast#}
    {#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}

    @@ -7108,7 +7245,7 @@ test "field access by string" {

    {#syntax#}@frame() *@Frame(func){#endsyntax#}

    This function returns a pointer to the frame for a given function. This type - can be {#link|implicitly cast|Implicit Casts#} to {#syntax#}anyframe->T{#endsyntax#} and + can be {#link|coerced|Type Coercion#} to {#syntax#}anyframe->T{#endsyntax#} and to {#syntax#}anyframe{#endsyntax#}, where {#syntax#}T{#endsyntax#} is the return type of the function in scope.

    @@ -7827,7 +7964,7 @@ test "vector @splat" { const scalar: u32 = 5; const result = @splat(4, scalar); comptime assert(@typeOf(result) == @Vector(4, u32)); - assert(std.mem.eql(u32, ([4]u32)(result), [_]u32{ 5, 5, 5, 5 })); + assert(std.mem.eql(u32, @as([4]u32, result), [_]u32{ 5, 5, 5, 5 })); } {#code_end#}

    @@ -8025,7 +8162,7 @@ test "integer truncation" {

    If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#}, - then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}. + then this is semantically equivalent to {#link|Type Coercion#}.

    {#header_close#} @@ -8529,7 +8666,7 @@ pub fn main() void { {#header_close#} {#header_open|Cast Truncates Data#}

    At compile-time:

    - {#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#} + {#code_begin|test_err|integer value 300 cannot be coerced to type 'u8'#} comptime { const spartan_count: u16 = 300; const byte = @intCast(u8, spartan_count); @@ -8665,7 +8802,7 @@ test "wraparound addition and subtraction" {

    At compile-time:

    {#code_begin|test_err|operation caused overflow#} comptime { - const x = @shlExact(u8(0b01010101), 2); + const x = @shlExact(@as(u8, 0b01010101), 2); } {#code_end#}

    At runtime:

    @@ -8683,7 +8820,7 @@ pub fn main() void {

    At compile-time:

    {#code_begin|test_err|exact shift shifted out 1 bits#} comptime { - const x = @shrExact(u8(0b10101010), 2); + const x = @shrExact(@as(u8, 0b10101010), 2); } {#code_end#}

    At runtime:

    @@ -9535,8 +9672,8 @@ const c = @cImport({

    {#syntax#}[*c]T{#endsyntax#} - C pointer.

    - +