mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
breaking syntax change: ??x to x.? (#1095)
See #1023 This also renames Nullable/Maybe to Optional
This commit is contained in:
parent
d464b25322
commit
ec1b6f6673
@ -75,7 +75,7 @@ pub fn build(b: *Builder) !void {
|
||||
cxx_compiler,
|
||||
"-print-file-name=libstdc++.a",
|
||||
});
|
||||
const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next();
|
||||
const libstdcxx_path = mem.split(libstdcxx_path_padded, "\r\n").next().?;
|
||||
if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) {
|
||||
warn(
|
||||
\\Unable to determine path to libstdc++.a
|
||||
|
||||
@ -6,7 +6,7 @@ Every type has a "handle". If a type is a simple primitive type such as i32 or
|
||||
f64, the handle is "by value", meaning that we pass around the value itself when
|
||||
we refer to a value of that type.
|
||||
|
||||
If a type is a container, error union, maybe type, slice, or array, then its
|
||||
If a type is a container, error union, optional type, slice, or array, then its
|
||||
handle is a pointer, and everywhere we refer to a value of this type we refer to
|
||||
a pointer.
|
||||
|
||||
@ -19,7 +19,7 @@ Error union types are represented as:
|
||||
payload: T,
|
||||
}
|
||||
|
||||
Maybe types are represented as:
|
||||
Optional types are represented as:
|
||||
|
||||
struct {
|
||||
payload: T,
|
||||
@ -28,6 +28,6 @@ Maybe types are represented as:
|
||||
|
||||
## Data Optimizations
|
||||
|
||||
Maybe pointer types are special: the 0x0 pointer value is used to represent a
|
||||
null pointer. Thus, instead of the struct above, maybe pointer types are
|
||||
Optional pointer types are special: the 0x0 pointer value is used to represent a
|
||||
null pointer. Thus, instead of the struct above, optional pointer types are
|
||||
represented as a `usize` in codegen and the handle is by value.
|
||||
|
||||
@ -156,18 +156,18 @@ pub fn main() void {
|
||||
true or false,
|
||||
!true);
|
||||
|
||||
// nullable
|
||||
var nullable_value: ?[]const u8 = null;
|
||||
assert(nullable_value == null);
|
||||
// optional
|
||||
var optional_value: ?[]const u8 = null;
|
||||
assert(optional_value == null);
|
||||
|
||||
warn("\nnullable 1\ntype: {}\nvalue: {}\n",
|
||||
@typeName(@typeOf(nullable_value)), nullable_value);
|
||||
warn("\noptional 1\ntype: {}\nvalue: {}\n",
|
||||
@typeName(@typeOf(optional_value)), optional_value);
|
||||
|
||||
nullable_value = "hi";
|
||||
assert(nullable_value != null);
|
||||
optional_value = "hi";
|
||||
assert(optional_value != null);
|
||||
|
||||
warn("\nnullable 2\ntype: {}\nvalue: {}\n",
|
||||
@typeName(@typeOf(nullable_value)), nullable_value);
|
||||
warn("\noptional 2\ntype: {}\nvalue: {}\n",
|
||||
@typeName(@typeOf(optional_value)), optional_value);
|
||||
|
||||
// error union
|
||||
var number_or_error: error!i32 = error.ArgNotFound;
|
||||
@ -428,7 +428,7 @@ pub fn main() void {
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>null</code></td>
|
||||
<td>used to set a nullable type to <code>null</code></td>
|
||||
<td>used to set an optional type to <code>null</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>undefined</code></td>
|
||||
@ -440,7 +440,7 @@ pub fn main() void {
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{#see_also|Nullables|this#}
|
||||
{#see_also|Optionals|this#}
|
||||
{#header_close#}
|
||||
{#header_open|String Literals#}
|
||||
{#code_begin|test#}
|
||||
@ -988,7 +988,7 @@ a ^= b</code></pre></td>
|
||||
<td><pre><code class="zig">a ?? b</code></pre></td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>{#link|Nullables#}</li>
|
||||
<li>{#link|Optionals#}</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>If <code>a</code> is <code>null</code>,
|
||||
@ -1003,10 +1003,10 @@ unwrapped == 1234</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre><code class="zig">??a</code></pre></td>
|
||||
<td><pre><code class="zig">a.?</code></pre></td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>{#link|Nullables#}</li>
|
||||
<li>{#link|Optionals#}</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
@ -1015,7 +1015,7 @@ unwrapped == 1234</code></pre>
|
||||
</td>
|
||||
<td>
|
||||
<pre><code class="zig">const value: ?u32 = 5678;
|
||||
??value == 5678</code></pre>
|
||||
value.? == 5678</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -1103,7 +1103,7 @@ unwrapped == 1234</code></pre>
|
||||
<td><pre><code class="zig">a == null<code></pre></td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>{#link|Nullables#}</li>
|
||||
<li>{#link|Optionals#}</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
@ -1267,8 +1267,8 @@ x.* == 1234</code></pre>
|
||||
{#header_open|Precedence#}
|
||||
<pre><code>x() x[] x.y
|
||||
a!b
|
||||
!x -x -%x ~x &x ?x ??x
|
||||
x{} x.*
|
||||
!x -x -%x ~x &x ?x
|
||||
x{} x.* x.?
|
||||
! * / % ** *%
|
||||
+ - ++ +% -%
|
||||
<< >>
|
||||
@ -1483,17 +1483,17 @@ test "volatile" {
|
||||
assert(@typeOf(mmio_ptr) == *volatile u8);
|
||||
}
|
||||
|
||||
test "nullable pointers" {
|
||||
// Pointers cannot be null. If you want a null pointer, use the nullable
|
||||
// prefix `?` to make the pointer type nullable.
|
||||
test "optional pointers" {
|
||||
// Pointers cannot be null. If you want a null pointer, use the optional
|
||||
// prefix `?` to make the pointer type optional.
|
||||
var ptr: ?*i32 = null;
|
||||
|
||||
var x: i32 = 1;
|
||||
ptr = &x;
|
||||
|
||||
assert((??ptr).* == 1);
|
||||
assert(ptr.?.* == 1);
|
||||
|
||||
// Nullable pointers are the same size as normal pointers, because pointer
|
||||
// Optional pointers are the same size as normal pointers, because pointer
|
||||
// value 0 is used as the null value.
|
||||
assert(@sizeOf(?*i32) == @sizeOf(*i32));
|
||||
}
|
||||
@ -1832,7 +1832,7 @@ test "linked list" {
|
||||
.last = &node,
|
||||
.len = 1,
|
||||
};
|
||||
assert((??list2.first).data == 1234);
|
||||
assert(list2.first.?.data == 1234);
|
||||
}
|
||||
{#code_end#}
|
||||
{#see_also|comptime|@fieldParentPtr#}
|
||||
@ -2270,7 +2270,7 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
|
||||
}
|
||||
|
||||
test "while null capture" {
|
||||
// Just like if expressions, while loops can take a nullable as the
|
||||
// Just like if expressions, while loops can take an optional as the
|
||||
// condition and capture the payload. When null is encountered the loop
|
||||
// exits.
|
||||
var sum1: u32 = 0;
|
||||
@ -2280,7 +2280,7 @@ test "while null capture" {
|
||||
}
|
||||
assert(sum1 == 3);
|
||||
|
||||
// The else branch is allowed on nullable iteration. In this case, it will
|
||||
// The else branch is allowed on optional iteration. In this case, it will
|
||||
// be executed on the first null value encountered.
|
||||
var sum2: u32 = 0;
|
||||
numbers_left = 3;
|
||||
@ -2340,7 +2340,7 @@ fn typeNameLength(comptime T: type) usize {
|
||||
return @typeName(T).len;
|
||||
}
|
||||
{#code_end#}
|
||||
{#see_also|if|Nullables|Errors|comptime|unreachable#}
|
||||
{#see_also|if|Optionals|Errors|comptime|unreachable#}
|
||||
{#header_close#}
|
||||
{#header_open|for#}
|
||||
{#code_begin|test|for#}
|
||||
@ -2400,7 +2400,7 @@ test "for else" {
|
||||
if (value == null) {
|
||||
break 9;
|
||||
} else {
|
||||
sum += ??value;
|
||||
sum += value.?;
|
||||
}
|
||||
} else blk: {
|
||||
assert(sum == 7);
|
||||
@ -2461,7 +2461,7 @@ test "if boolean" {
|
||||
assert(result == 47);
|
||||
}
|
||||
|
||||
test "if nullable" {
|
||||
test "if optional" {
|
||||
// If expressions test for null.
|
||||
|
||||
const a: ?u32 = 0;
|
||||
@ -2544,7 +2544,7 @@ test "if error union" {
|
||||
}
|
||||
}
|
||||
{#code_end#}
|
||||
{#see_also|Nullables|Errors#}
|
||||
{#see_also|Optionals|Errors#}
|
||||
{#header_close#}
|
||||
{#header_open|defer#}
|
||||
{#code_begin|test|defer#}
|
||||
@ -3167,24 +3167,24 @@ test "inferred error set" {
|
||||
<p>TODO</p>
|
||||
{#header_close#}
|
||||
{#header_close#}
|
||||
{#header_open|Nullables#}
|
||||
{#header_open|Optionals#}
|
||||
<p>
|
||||
One area that Zig provides safety without compromising efficiency or
|
||||
readability is with the nullable type.
|
||||
readability is with the optional type.
|
||||
</p>
|
||||
<p>
|
||||
The question mark symbolizes the nullable type. You can convert a type to a nullable
|
||||
The question mark symbolizes the optional type. You can convert a type to an optional
|
||||
type by putting a question mark in front of it, like this:
|
||||
</p>
|
||||
{#code_begin|syntax#}
|
||||
// normal integer
|
||||
const normal_int: i32 = 1234;
|
||||
|
||||
// nullable integer
|
||||
const nullable_int: ?i32 = 5678;
|
||||
// optional integer
|
||||
const optional_int: ?i32 = 5678;
|
||||
{#code_end#}
|
||||
<p>
|
||||
Now the variable <code>nullable_int</code> could be an <code>i32</code>, or <code>null</code>.
|
||||
Now the variable <code>optional_int</code> could be an <code>i32</code>, or <code>null</code>.
|
||||
</p>
|
||||
<p>
|
||||
Instead of integers, let's talk about pointers. Null references are the source of many runtime
|
||||
@ -3193,8 +3193,8 @@ const nullable_int: ?i32 = 5678;
|
||||
</p>
|
||||
<p>Zig does not have them.</p>
|
||||
<p>
|
||||
Instead, you can use a nullable pointer. This secretly compiles down to a normal pointer,
|
||||
since we know we can use 0 as the null value for the nullable type. But the compiler
|
||||
Instead, you can use an optional pointer. This secretly compiles down to a normal pointer,
|
||||
since we know we can use 0 as the null value for the optional type. But the compiler
|
||||
can check your work and make sure you don't assign null to something that can't be null.
|
||||
</p>
|
||||
<p>
|
||||
@ -3226,7 +3226,7 @@ fn doAThing() ?*Foo {
|
||||
<p>
|
||||
Here, Zig is at least as convenient, if not more, than C. And, the type of "ptr"
|
||||
is <code>*u8</code> <em>not</em> <code>?*u8</code>. The <code>??</code> operator
|
||||
unwrapped the nullable type and therefore <code>ptr</code> is guaranteed to be non-null everywhere
|
||||
unwrapped the optional type and therefore <code>ptr</code> is guaranteed to be non-null everywhere
|
||||
it is used in the function.
|
||||
</p>
|
||||
<p>
|
||||
@ -3245,10 +3245,10 @@ fn doAThing() ?*Foo {
|
||||
In Zig you can accomplish the same thing:
|
||||
</p>
|
||||
{#code_begin|syntax#}
|
||||
fn doAThing(nullable_foo: ?*Foo) void {
|
||||
fn doAThing(optional_foo: ?*Foo) void {
|
||||
// do some stuff
|
||||
|
||||
if (nullable_foo) |foo| {
|
||||
if (optional_foo) |foo| {
|
||||
doSomethingWithFoo(foo);
|
||||
}
|
||||
|
||||
@ -3257,7 +3257,7 @@ fn doAThing(nullable_foo: ?*Foo) void {
|
||||
{#code_end#}
|
||||
<p>
|
||||
Once again, the notable thing here is that inside the if block,
|
||||
<code>foo</code> is no longer a nullable pointer, it is a pointer, which
|
||||
<code>foo</code> is no longer an optional pointer, it is a pointer, which
|
||||
cannot be null.
|
||||
</p>
|
||||
<p>
|
||||
@ -3267,20 +3267,20 @@ fn doAThing(nullable_foo: ?*Foo) void {
|
||||
The optimizer can sometimes make better decisions knowing that pointer arguments
|
||||
cannot be null.
|
||||
</p>
|
||||
{#header_open|Nullable Type#}
|
||||
<p>A nullable is created by putting <code>?</code> in front of a type. You can use compile-time
|
||||
reflection to access the child type of a nullable:</p>
|
||||
{#header_open|Optional Type#}
|
||||
<p>An optional is created by putting <code>?</code> in front of a type. You can use compile-time
|
||||
reflection to access the child type of an optional:</p>
|
||||
{#code_begin|test#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "nullable type" {
|
||||
// Declare a nullable and implicitly cast from null:
|
||||
test "optional type" {
|
||||
// Declare an optional and implicitly cast from null:
|
||||
var foo: ?i32 = null;
|
||||
|
||||
// Implicitly cast from child type of a nullable
|
||||
// Implicitly cast from child type of an optional
|
||||
foo = 1234;
|
||||
|
||||
// Use compile-time reflection to access the child type of the nullable:
|
||||
// Use compile-time reflection to access the child type of the optional:
|
||||
comptime assert(@typeOf(foo).Child == i32);
|
||||
}
|
||||
{#code_end#}
|
||||
@ -4888,7 +4888,7 @@ pub const TypeId = enum {
|
||||
ComptimeInt,
|
||||
Undefined,
|
||||
Null,
|
||||
Nullable,
|
||||
Optional,
|
||||
ErrorUnion,
|
||||
Error,
|
||||
Enum,
|
||||
@ -4922,7 +4922,7 @@ pub const TypeInfo = union(TypeId) {
|
||||
ComptimeInt: void,
|
||||
Undefined: void,
|
||||
Null: void,
|
||||
Nullable: Nullable,
|
||||
Optional: Optional,
|
||||
ErrorUnion: ErrorUnion,
|
||||
ErrorSet: ErrorSet,
|
||||
Enum: Enum,
|
||||
@ -4975,7 +4975,7 @@ pub const TypeInfo = union(TypeId) {
|
||||
defs: []Definition,
|
||||
};
|
||||
|
||||
pub const Nullable = struct {
|
||||
pub const Optional = struct {
|
||||
child: type,
|
||||
};
|
||||
|
||||
@ -5366,8 +5366,8 @@ comptime {
|
||||
<p>At compile-time:</p>
|
||||
{#code_begin|test_err|unable to unwrap null#}
|
||||
comptime {
|
||||
const nullable_number: ?i32 = null;
|
||||
const number = ??nullable_number;
|
||||
const optional_number: ?i32 = null;
|
||||
const number = optional_number.?;
|
||||
}
|
||||
{#code_end#}
|
||||
<p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p>
|
||||
@ -5376,9 +5376,9 @@ comptime {
|
||||
{#code_begin|exe|test#}
|
||||
const warn = @import("std").debug.warn;
|
||||
pub fn main() void {
|
||||
const nullable_number: ?i32 = null;
|
||||
const optional_number: ?i32 = null;
|
||||
|
||||
if (nullable_number) |number| {
|
||||
if (optional_number) |number| {
|
||||
warn("got number: {}\n", number);
|
||||
} else {
|
||||
warn("it's null\n");
|
||||
@ -5939,9 +5939,9 @@ AsmInputItem = "[" Symbol "]" String "(" Expression ")"
|
||||
|
||||
AsmClobbers= ":" list(String, ",")
|
||||
|
||||
UnwrapExpression = BoolOrExpression (UnwrapNullable | UnwrapError) | BoolOrExpression
|
||||
UnwrapExpression = BoolOrExpression (UnwrapOptional | UnwrapError) | BoolOrExpression
|
||||
|
||||
UnwrapNullable = "??" Expression
|
||||
UnwrapOptional = "??" Expression
|
||||
|
||||
UnwrapError = "catch" option("|" Symbol "|") Expression
|
||||
|
||||
@ -6015,12 +6015,10 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
|
||||
|
||||
PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression
|
||||
|
||||
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression)
|
||||
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ".*" | ".?")
|
||||
|
||||
FieldAccessExpression = "." Symbol
|
||||
|
||||
PtrDerefExpression = ".*"
|
||||
|
||||
FnCallExpression = "(" list(Expression, ",") ")"
|
||||
|
||||
ArrayAccessExpression = "[" Expression "]"
|
||||
@ -6033,7 +6031,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
|
||||
|
||||
StructLiteralField = "." Symbol "=" Expression
|
||||
|
||||
PrefixOp = "!" | "-" | "~" | (("*" | "[*]") option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
|
||||
PrefixOp = "!" | "-" | "~" | (("*" | "[*]") option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "-%" | "try" | "await"
|
||||
|
||||
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ const allocator = std.debug.global_allocator;
|
||||
|
||||
pub fn main() !void {
|
||||
var args_it = os.args();
|
||||
const exe = try unwrapArg(??args_it.next(allocator));
|
||||
const exe = try unwrapArg(args_it.next(allocator).?);
|
||||
var catted_anything = false;
|
||||
var stdout_file = try io.getStdOut();
|
||||
|
||||
|
||||
@ -99,7 +99,7 @@ pub const Args = struct {
|
||||
error.ArgumentNotInAllowedSet => {
|
||||
std.debug.warn("argument '{}' is invalid for flag '{}'\n", args[i], arg);
|
||||
std.debug.warn("allowed options are ");
|
||||
for (??flag.allowed_set) |possible| {
|
||||
for (flag.allowed_set.?) |possible| {
|
||||
std.debug.warn("'{}' ", possible);
|
||||
}
|
||||
std.debug.warn("\n");
|
||||
@ -276,14 +276,14 @@ test "parse arguments" {
|
||||
debug.assert(!args.present("help2"));
|
||||
debug.assert(!args.present("init"));
|
||||
|
||||
debug.assert(mem.eql(u8, ??args.single("build-file"), "build.zig"));
|
||||
debug.assert(mem.eql(u8, ??args.single("color"), "on"));
|
||||
debug.assert(mem.eql(u8, args.single("build-file").?, "build.zig"));
|
||||
debug.assert(mem.eql(u8, args.single("color").?, "on"));
|
||||
|
||||
const objects = ??args.many("object");
|
||||
const objects = args.many("object").?;
|
||||
debug.assert(mem.eql(u8, objects[0], "obj1"));
|
||||
debug.assert(mem.eql(u8, objects[1], "obj2"));
|
||||
|
||||
debug.assert(mem.eql(u8, ??args.single("library"), "lib2"));
|
||||
debug.assert(mem.eql(u8, args.single("library").?, "lib2"));
|
||||
|
||||
const pos = args.positionals.toSliceConst();
|
||||
debug.assert(mem.eql(u8, pos[0], "build"));
|
||||
|
||||
@ -8,6 +8,6 @@ pub const ContextRef = removeNullability(c.LLVMContextRef);
|
||||
pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
|
||||
|
||||
fn removeNullability(comptime T: type) type {
|
||||
comptime assert(@typeId(T) == builtin.TypeId.Nullable);
|
||||
comptime assert(@typeId(T) == builtin.TypeId.Optional);
|
||||
return T.Child;
|
||||
}
|
||||
|
||||
@ -490,7 +490,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
|
||||
try stderr.print("encountered --pkg-end with no matching --pkg-begin\n");
|
||||
os.exit(1);
|
||||
}
|
||||
cur_pkg = ??cur_pkg.parent;
|
||||
cur_pkg = cur_pkg.parent.?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,7 +514,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
|
||||
},
|
||||
}
|
||||
|
||||
const basename = os.path.basename(??in_file);
|
||||
const basename = os.path.basename(in_file.?);
|
||||
var it = mem.split(basename, ".");
|
||||
const root_name = it.next() ?? {
|
||||
try stderr.write("file name cannot be empty\n");
|
||||
@ -523,12 +523,12 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
|
||||
|
||||
const asm_a = flags.many("assembly");
|
||||
const obj_a = flags.many("object");
|
||||
if (in_file == null and (obj_a == null or (??obj_a).len == 0) and (asm_a == null or (??asm_a).len == 0)) {
|
||||
if (in_file == null and (obj_a == null or obj_a.?.len == 0) and (asm_a == null or asm_a.?.len == 0)) {
|
||||
try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");
|
||||
os.exit(1);
|
||||
}
|
||||
|
||||
if (out_type == Module.Kind.Obj and (obj_a != null and (??obj_a).len != 0)) {
|
||||
if (out_type == Module.Kind.Obj and (obj_a != null and obj_a.?.len != 0)) {
|
||||
try stderr.write("When building an object file, --object arguments are invalid\n");
|
||||
os.exit(1);
|
||||
}
|
||||
|
||||
@ -145,8 +145,8 @@ enum ConstPtrSpecial {
|
||||
// emit a binary with a compile time known address.
|
||||
// In this case index is the numeric address value.
|
||||
// We also use this for null pointer. We need the data layout for ConstCastOnly == true
|
||||
// types to be the same, so all nullables of pointer types use x_ptr
|
||||
// instead of x_nullable
|
||||
// types to be the same, so all optionals of pointer types use x_ptr
|
||||
// instead of x_optional
|
||||
ConstPtrSpecialHardCodedAddr,
|
||||
// This means that the pointer represents memory of assigning to _.
|
||||
// That is, storing discards the data, and loading is invalid.
|
||||
@ -222,10 +222,10 @@ enum RuntimeHintErrorUnion {
|
||||
RuntimeHintErrorUnionNonError,
|
||||
};
|
||||
|
||||
enum RuntimeHintMaybe {
|
||||
RuntimeHintMaybeUnknown,
|
||||
RuntimeHintMaybeNull, // TODO is this value even possible? if this is the case it might mean the const value is compile time known.
|
||||
RuntimeHintMaybeNonNull,
|
||||
enum RuntimeHintOptional {
|
||||
RuntimeHintOptionalUnknown,
|
||||
RuntimeHintOptionalNull, // TODO is this value even possible? if this is the case it might mean the const value is compile time known.
|
||||
RuntimeHintOptionalNonNull,
|
||||
};
|
||||
|
||||
enum RuntimeHintPtr {
|
||||
@ -254,7 +254,7 @@ struct ConstExprValue {
|
||||
bool x_bool;
|
||||
ConstBoundFnValue x_bound_fn;
|
||||
TypeTableEntry *x_type;
|
||||
ConstExprValue *x_nullable;
|
||||
ConstExprValue *x_optional;
|
||||
ConstErrValue x_err_union;
|
||||
ErrorTableEntry *x_err_set;
|
||||
BigInt x_enum_tag;
|
||||
@ -268,7 +268,7 @@ struct ConstExprValue {
|
||||
|
||||
// populated if special == ConstValSpecialRuntime
|
||||
RuntimeHintErrorUnion rh_error_union;
|
||||
RuntimeHintMaybe rh_maybe;
|
||||
RuntimeHintOptional rh_maybe;
|
||||
RuntimeHintPtr rh_ptr;
|
||||
} data;
|
||||
};
|
||||
@ -556,7 +556,7 @@ enum BinOpType {
|
||||
BinOpTypeMultWrap,
|
||||
BinOpTypeDiv,
|
||||
BinOpTypeMod,
|
||||
BinOpTypeUnwrapMaybe,
|
||||
BinOpTypeUnwrapOptional,
|
||||
BinOpTypeArrayCat,
|
||||
BinOpTypeArrayMult,
|
||||
BinOpTypeErrorUnion,
|
||||
@ -623,8 +623,8 @@ enum PrefixOp {
|
||||
PrefixOpBinNot,
|
||||
PrefixOpNegation,
|
||||
PrefixOpNegationWrap,
|
||||
PrefixOpMaybe,
|
||||
PrefixOpUnwrapMaybe,
|
||||
PrefixOpOptional,
|
||||
PrefixOpUnwrapOptional,
|
||||
PrefixOpAddrOf,
|
||||
};
|
||||
|
||||
@ -1052,7 +1052,7 @@ struct TypeTableEntryStruct {
|
||||
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
|
||||
};
|
||||
|
||||
struct TypeTableEntryMaybe {
|
||||
struct TypeTableEntryOptional {
|
||||
TypeTableEntry *child_type;
|
||||
};
|
||||
|
||||
@ -1175,7 +1175,7 @@ enum TypeTableEntryId {
|
||||
TypeTableEntryIdComptimeInt,
|
||||
TypeTableEntryIdUndefined,
|
||||
TypeTableEntryIdNull,
|
||||
TypeTableEntryIdMaybe,
|
||||
TypeTableEntryIdOptional,
|
||||
TypeTableEntryIdErrorUnion,
|
||||
TypeTableEntryIdErrorSet,
|
||||
TypeTableEntryIdEnum,
|
||||
@ -1206,7 +1206,7 @@ struct TypeTableEntry {
|
||||
TypeTableEntryFloat floating;
|
||||
TypeTableEntryArray array;
|
||||
TypeTableEntryStruct structure;
|
||||
TypeTableEntryMaybe maybe;
|
||||
TypeTableEntryOptional maybe;
|
||||
TypeTableEntryErrorUnion error_union;
|
||||
TypeTableEntryErrorSet error_set;
|
||||
TypeTableEntryEnum enumeration;
|
||||
@ -1402,7 +1402,7 @@ enum PanicMsgId {
|
||||
PanicMsgIdRemainderDivisionByZero,
|
||||
PanicMsgIdExactDivisionRemainder,
|
||||
PanicMsgIdSliceWidenRemainder,
|
||||
PanicMsgIdUnwrapMaybeFail,
|
||||
PanicMsgIdUnwrapOptionalFail,
|
||||
PanicMsgIdInvalidErrorCode,
|
||||
PanicMsgIdIncorrectAlignment,
|
||||
PanicMsgIdBadUnionField,
|
||||
@ -2016,8 +2016,8 @@ enum IrInstructionId {
|
||||
IrInstructionIdAsm,
|
||||
IrInstructionIdSizeOf,
|
||||
IrInstructionIdTestNonNull,
|
||||
IrInstructionIdUnwrapMaybe,
|
||||
IrInstructionIdMaybeWrap,
|
||||
IrInstructionIdUnwrapOptional,
|
||||
IrInstructionIdOptionalWrap,
|
||||
IrInstructionIdUnionTag,
|
||||
IrInstructionIdClz,
|
||||
IrInstructionIdCtz,
|
||||
@ -2184,7 +2184,7 @@ enum IrUnOp {
|
||||
IrUnOpNegation,
|
||||
IrUnOpNegationWrap,
|
||||
IrUnOpDereference,
|
||||
IrUnOpMaybe,
|
||||
IrUnOpOptional,
|
||||
};
|
||||
|
||||
struct IrInstructionUnOp {
|
||||
@ -2487,7 +2487,7 @@ struct IrInstructionTestNonNull {
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionUnwrapMaybe {
|
||||
struct IrInstructionUnwrapOptional {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
@ -2745,7 +2745,7 @@ struct IrInstructionUnwrapErrPayload {
|
||||
bool safety_check_on;
|
||||
};
|
||||
|
||||
struct IrInstructionMaybeWrap {
|
||||
struct IrInstructionOptionalWrap {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
@ -2954,10 +2954,10 @@ struct IrInstructionExport {
|
||||
struct IrInstructionErrorReturnTrace {
|
||||
IrInstruction base;
|
||||
|
||||
enum Nullable {
|
||||
enum Optional {
|
||||
Null,
|
||||
NonNull,
|
||||
} nullable;
|
||||
} optional;
|
||||
};
|
||||
|
||||
struct IrInstructionErrorUnion {
|
||||
|
||||
@ -236,7 +236,7 @@ bool type_is_complete(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdFn:
|
||||
@ -272,7 +272,7 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdFn:
|
||||
@ -520,7 +520,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
|
||||
} else {
|
||||
ensure_complete_type(g, child_type);
|
||||
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMaybe);
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdOptional);
|
||||
assert(child_type->type_ref || child_type->zero_bits);
|
||||
assert(child_type->di_type);
|
||||
entry->is_copyable = type_is_copyable(g, child_type);
|
||||
@ -1361,7 +1361,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
|
||||
return type_entry->data.structure.layout == ContainerLayoutPacked;
|
||||
case TypeTableEntryIdUnion:
|
||||
return type_entry->data.unionation.layout == ContainerLayoutPacked;
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
return type_is_codegen_pointer(child_type);
|
||||
@ -1415,7 +1415,7 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
return type_allowed_in_extern(g, type_entry->data.pointer.child_type);
|
||||
case TypeTableEntryIdStruct:
|
||||
return type_entry->data.structure.layout == ContainerLayoutExtern || type_entry->data.structure.layout == ContainerLayoutPacked;
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
|
||||
@ -1538,7 +1538,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -1632,7 +1632,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -2985,8 +2985,8 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
}
|
||||
|
||||
TypeTableEntry *nullable_ptr_to_stack_trace_type = get_maybe_type(g, get_ptr_to_stack_trace_type(g));
|
||||
if (fn_type_id->param_info[1].type != nullable_ptr_to_stack_trace_type) {
|
||||
TypeTableEntry *optional_ptr_to_stack_trace_type = get_maybe_type(g, get_ptr_to_stack_trace_type(g));
|
||||
if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
}
|
||||
|
||||
@ -3368,7 +3368,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -3746,7 +3746,7 @@ static bool is_container(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdFn:
|
||||
@ -3805,7 +3805,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdFn:
|
||||
@ -3824,7 +3824,7 @@ TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) {
|
||||
if (type->id == TypeTableEntryIdPointer) return type;
|
||||
if (type->id == TypeTableEntryIdFn) return type;
|
||||
if (type->id == TypeTableEntryIdPromise) return type;
|
||||
if (type->id == TypeTableEntryIdMaybe) {
|
||||
if (type->id == TypeTableEntryIdOptional) {
|
||||
if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type;
|
||||
if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type;
|
||||
if (type->data.maybe.child_type->id == TypeTableEntryIdPromise) return type->data.maybe.child_type;
|
||||
@ -4331,7 +4331,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
||||
return type_has_bits(type_entry);
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
return type_has_bits(type_entry->data.error_union.payload_type);
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
return type_has_bits(type_entry->data.maybe.child_type) &&
|
||||
!type_is_codegen_pointer(type_entry->data.maybe.child_type);
|
||||
case TypeTableEntryIdUnion:
|
||||
@ -4709,12 +4709,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
case TypeTableEntryIdUnion:
|
||||
// TODO better hashing algorithm
|
||||
return 2709806591;
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
if (get_codegen_ptr_type(const_val->type) != nullptr) {
|
||||
return hash_const_val(const_val) * 1992916303;
|
||||
} else {
|
||||
if (const_val->data.x_nullable) {
|
||||
return hash_const_val(const_val->data.x_nullable) * 1992916303;
|
||||
if (const_val->data.x_optional) {
|
||||
return hash_const_val(const_val->data.x_optional) * 1992916303;
|
||||
} else {
|
||||
return 4016830364;
|
||||
}
|
||||
@ -4817,12 +4817,12 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
|
||||
}
|
||||
return false;
|
||||
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
if (get_codegen_ptr_type(value->type) != nullptr)
|
||||
return value->data.x_ptr.mut == ConstPtrMutComptimeVar;
|
||||
if (value->data.x_nullable == nullptr)
|
||||
if (value->data.x_optional == nullptr)
|
||||
return false;
|
||||
return can_mutate_comptime_var_state(value->data.x_nullable);
|
||||
return can_mutate_comptime_var_state(value->data.x_optional);
|
||||
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
if (value->data.x_err_union.err != nullptr)
|
||||
@ -4869,7 +4869,7 @@ static bool return_type_is_cacheable(TypeTableEntry *return_type) {
|
||||
case TypeTableEntryIdUnion:
|
||||
return false;
|
||||
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
return return_type_is_cacheable(return_type->data.maybe.child_type);
|
||||
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
@ -4978,7 +4978,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdUnion:
|
||||
assert(type_has_zero_bits_known(type_entry));
|
||||
return type_entry->data.unionation.requires_comptime;
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
return type_requires_comptime(type_entry->data.maybe.child_type);
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
return type_requires_comptime(type_entry->data.error_union.payload_type);
|
||||
@ -5460,13 +5460,13 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdNull:
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
if (get_codegen_ptr_type(a->type) != nullptr)
|
||||
return const_values_equal_ptr(a, b);
|
||||
if (a->data.x_nullable == nullptr || b->data.x_nullable == nullptr) {
|
||||
return (a->data.x_nullable == nullptr && b->data.x_nullable == nullptr);
|
||||
if (a->data.x_optional == nullptr || b->data.x_optional == nullptr) {
|
||||
return (a->data.x_optional == nullptr && b->data.x_optional == nullptr);
|
||||
} else {
|
||||
return const_values_equal(a->data.x_nullable, b->data.x_nullable);
|
||||
return const_values_equal(a->data.x_optional, b->data.x_optional);
|
||||
}
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
zig_panic("TODO");
|
||||
@ -5708,12 +5708,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
buf_appendf(buf, "undefined");
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
{
|
||||
if (get_codegen_ptr_type(const_val->type) != nullptr)
|
||||
return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
|
||||
if (const_val->data.x_nullable) {
|
||||
render_const_value(g, buf, const_val->data.x_nullable);
|
||||
if (const_val->data.x_optional) {
|
||||
render_const_value(g, buf, const_val->data.x_optional);
|
||||
} else {
|
||||
buf_appendf(buf, "null");
|
||||
}
|
||||
@ -5819,7 +5819,7 @@ uint32_t type_id_hash(TypeId x) {
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
@ -5865,7 +5865,7 @@ bool type_id_eql(TypeId a, TypeId b) {
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdPromise:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -5987,7 +5987,7 @@ static const TypeTableEntryId all_type_ids[] = {
|
||||
TypeTableEntryIdComptimeInt,
|
||||
TypeTableEntryIdUndefined,
|
||||
TypeTableEntryIdNull,
|
||||
TypeTableEntryIdMaybe,
|
||||
TypeTableEntryIdOptional,
|
||||
TypeTableEntryIdErrorUnion,
|
||||
TypeTableEntryIdErrorSet,
|
||||
TypeTableEntryIdEnum,
|
||||
@ -6042,7 +6042,7 @@ size_t type_id_index(TypeTableEntry *entry) {
|
||||
return 11;
|
||||
case TypeTableEntryIdNull:
|
||||
return 12;
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
return 13;
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
return 14;
|
||||
@ -6100,8 +6100,8 @@ const char *type_id_name(TypeTableEntryId id) {
|
||||
return "Undefined";
|
||||
case TypeTableEntryIdNull:
|
||||
return "Null";
|
||||
case TypeTableEntryIdMaybe:
|
||||
return "Nullable";
|
||||
case TypeTableEntryIdOptional:
|
||||
return "Optional";
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
return "ErrorUnion";
|
||||
case TypeTableEntryIdErrorSet:
|
||||
|
||||
@ -50,7 +50,7 @@ static const char *bin_op_str(BinOpType bin_op) {
|
||||
case BinOpTypeAssignBitXor: return "^=";
|
||||
case BinOpTypeAssignBitOr: return "|=";
|
||||
case BinOpTypeAssignMergeErrorSets: return "||=";
|
||||
case BinOpTypeUnwrapMaybe: return "??";
|
||||
case BinOpTypeUnwrapOptional: return "??";
|
||||
case BinOpTypeArrayCat: return "++";
|
||||
case BinOpTypeArrayMult: return "**";
|
||||
case BinOpTypeErrorUnion: return "!";
|
||||
@ -66,8 +66,8 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
|
||||
case PrefixOpNegationWrap: return "-%";
|
||||
case PrefixOpBoolNot: return "!";
|
||||
case PrefixOpBinNot: return "~";
|
||||
case PrefixOpMaybe: return "?";
|
||||
case PrefixOpUnwrapMaybe: return "??";
|
||||
case PrefixOpOptional: return "?";
|
||||
case PrefixOpUnwrapOptional: return "??";
|
||||
case PrefixOpAddrOf: return "&";
|
||||
}
|
||||
zig_unreachable();
|
||||
|
||||
@ -865,7 +865,7 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
|
||||
return buf_create_from_str("exact division produced remainder");
|
||||
case PanicMsgIdSliceWidenRemainder:
|
||||
return buf_create_from_str("slice widening size mismatch");
|
||||
case PanicMsgIdUnwrapMaybeFail:
|
||||
case PanicMsgIdUnwrapOptionalFail:
|
||||
return buf_create_from_str("attempt to unwrap null");
|
||||
case PanicMsgIdUnreachable:
|
||||
return buf_create_from_str("reached unreachable code");
|
||||
@ -2734,7 +2734,7 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
|
||||
|
||||
switch (op_id) {
|
||||
case IrUnOpInvalid:
|
||||
case IrUnOpMaybe:
|
||||
case IrUnOpOptional:
|
||||
case IrUnOpDereference:
|
||||
zig_unreachable();
|
||||
case IrUnOpNegation:
|
||||
@ -3333,7 +3333,7 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLVMValueRef maybe_handle) {
|
||||
assert(maybe_type->id == TypeTableEntryIdMaybe);
|
||||
assert(maybe_type->id == TypeTableEntryIdOptional);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
if (child_type->zero_bits) {
|
||||
return maybe_handle;
|
||||
@ -3355,23 +3355,23 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapMaybe *instruction)
|
||||
IrInstructionUnwrapOptional *instruction)
|
||||
{
|
||||
TypeTableEntry *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type;
|
||||
assert(maybe_type->id == TypeTableEntryIdMaybe);
|
||||
assert(maybe_type->id == TypeTableEntryIdOptional);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
|
||||
LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk");
|
||||
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeFail");
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
|
||||
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
|
||||
LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, fail_block);
|
||||
gen_safety_crash(g, PanicMsgIdUnwrapMaybeFail);
|
||||
gen_safety_crash(g, PanicMsgIdUnwrapOptionalFail);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
@ -3593,17 +3593,17 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
|
||||
} else if (target_type->id == TypeTableEntryIdFn) {
|
||||
align_bytes = target_type->data.fn.fn_type_id.alignment;
|
||||
ptr_val = target_val;
|
||||
} else if (target_type->id == TypeTableEntryIdMaybe &&
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdPointer)
|
||||
{
|
||||
align_bytes = target_type->data.maybe.child_type->data.pointer.alignment;
|
||||
ptr_val = target_val;
|
||||
} else if (target_type->id == TypeTableEntryIdMaybe &&
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdFn)
|
||||
{
|
||||
align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
|
||||
ptr_val = target_val;
|
||||
} else if (target_type->id == TypeTableEntryIdMaybe &&
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdPromise)
|
||||
{
|
||||
zig_panic("TODO audit this function");
|
||||
@ -3705,7 +3705,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
|
||||
success_order, failure_order, instruction->is_weak);
|
||||
|
||||
TypeTableEntry *maybe_type = instruction->base.value.type;
|
||||
assert(maybe_type->id == TypeTableEntryIdMaybe);
|
||||
assert(maybe_type->id == TypeTableEntryIdOptional);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
|
||||
if (type_is_codegen_pointer(child_type)) {
|
||||
@ -4115,10 +4115,10 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionMaybeWrap *instruction) {
|
||||
static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
|
||||
assert(wanted_type->id == TypeTableEntryIdMaybe);
|
||||
assert(wanted_type->id == TypeTableEntryIdOptional);
|
||||
|
||||
TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
|
||||
|
||||
@ -4699,8 +4699,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
|
||||
case IrInstructionIdTestNonNull:
|
||||
return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
|
||||
case IrInstructionIdUnwrapMaybe:
|
||||
return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapMaybe *)instruction);
|
||||
case IrInstructionIdUnwrapOptional:
|
||||
return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);
|
||||
case IrInstructionIdClz:
|
||||
return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
|
||||
case IrInstructionIdCtz:
|
||||
@ -4741,8 +4741,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);
|
||||
case IrInstructionIdUnwrapErrPayload:
|
||||
return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction);
|
||||
case IrInstructionIdMaybeWrap:
|
||||
return ir_render_maybe_wrap(g, executable, (IrInstructionMaybeWrap *)instruction);
|
||||
case IrInstructionIdOptionalWrap:
|
||||
return ir_render_maybe_wrap(g, executable, (IrInstructionOptionalWrap *)instruction);
|
||||
case IrInstructionIdErrWrapCode:
|
||||
return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
|
||||
case IrInstructionIdErrWrapPayload:
|
||||
@ -4972,7 +4972,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
}
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdPromise:
|
||||
{
|
||||
LLVMValueRef ptr_val = gen_const_val(g, const_val, "");
|
||||
@ -5137,19 +5137,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
} else {
|
||||
return LLVMConstNull(LLVMInt1Type());
|
||||
}
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
if (child_type->zero_bits) {
|
||||
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_nullable ? 1 : 0, false);
|
||||
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
|
||||
} else if (type_is_codegen_pointer(child_type)) {
|
||||
return gen_const_val_ptr(g, const_val, name);
|
||||
} else {
|
||||
LLVMValueRef child_val;
|
||||
LLVMValueRef maybe_val;
|
||||
bool make_unnamed_struct;
|
||||
if (const_val->data.x_nullable) {
|
||||
child_val = gen_const_val(g, const_val->data.x_nullable, "");
|
||||
if (const_val->data.x_optional) {
|
||||
child_val = gen_const_val(g, const_val->data.x_optional, "");
|
||||
maybe_val = LLVMConstAllOnes(LLVMInt1Type());
|
||||
|
||||
make_unnamed_struct = is_llvm_value_unnamed_type(const_val->type, child_val);
|
||||
@ -5755,8 +5755,8 @@ static void do_code_gen(CodeGen *g) {
|
||||
} else if (instruction->id == IrInstructionIdSlice) {
|
||||
IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
|
||||
slot = &slice_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdMaybeWrap) {
|
||||
IrInstructionMaybeWrap *maybe_wrap_instruction = (IrInstructionMaybeWrap *)instruction;
|
||||
} else if (instruction->id == IrInstructionIdOptionalWrap) {
|
||||
IrInstructionOptionalWrap *maybe_wrap_instruction = (IrInstructionOptionalWrap *)instruction;
|
||||
slot = &maybe_wrap_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdErrWrapPayload) {
|
||||
IrInstructionErrWrapPayload *err_wrap_payload_instruction = (IrInstructionErrWrapPayload *)instruction;
|
||||
@ -6511,7 +6511,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||
" ComptimeInt: void,\n"
|
||||
" Undefined: void,\n"
|
||||
" Null: void,\n"
|
||||
" Nullable: Nullable,\n"
|
||||
" Optional: Optional,\n"
|
||||
" ErrorUnion: ErrorUnion,\n"
|
||||
" ErrorSet: ErrorSet,\n"
|
||||
" Enum: Enum,\n"
|
||||
@ -6570,7 +6570,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||
" defs: []Definition,\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" pub const Nullable = struct {\n"
|
||||
" pub const Optional = struct {\n"
|
||||
" child: type,\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
@ -7145,7 +7145,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry
|
||||
case TypeTableEntryIdArray:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
|
||||
return;
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
|
||||
return;
|
||||
case TypeTableEntryIdFn:
|
||||
@ -7234,7 +7234,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
|
||||
buf_appendf(out_buf, "%s%s *", const_str, buf_ptr(&child_buf));
|
||||
break;
|
||||
}
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
if (child_type->zero_bits) {
|
||||
@ -7448,7 +7448,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdPromise:
|
||||
zig_unreachable();
|
||||
|
||||
198
src/ir.cpp
198
src/ir.cpp
@ -47,7 +47,7 @@ enum ConstCastResultId {
|
||||
ConstCastResultIdErrSetGlobal,
|
||||
ConstCastResultIdPointerChild,
|
||||
ConstCastResultIdSliceChild,
|
||||
ConstCastResultIdNullableChild,
|
||||
ConstCastResultIdOptionalChild,
|
||||
ConstCastResultIdErrorUnionPayload,
|
||||
ConstCastResultIdErrorUnionErrorSet,
|
||||
ConstCastResultIdFnAlign,
|
||||
@ -86,7 +86,7 @@ struct ConstCastOnly {
|
||||
ConstCastErrSetMismatch error_set;
|
||||
ConstCastOnly *pointer_child;
|
||||
ConstCastOnly *slice_child;
|
||||
ConstCastOnly *nullable_child;
|
||||
ConstCastOnly *optional_child;
|
||||
ConstCastOnly *error_union_payload;
|
||||
ConstCastOnly *error_union_error_set;
|
||||
ConstCastOnly *return_type;
|
||||
@ -372,8 +372,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
|
||||
return IrInstructionIdTestNonNull;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapMaybe *) {
|
||||
return IrInstructionIdUnwrapMaybe;
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {
|
||||
return IrInstructionIdUnwrapOptional;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
|
||||
@ -524,8 +524,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrPayload
|
||||
return IrInstructionIdUnwrapErrPayload;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionMaybeWrap *) {
|
||||
return IrInstructionIdMaybeWrap;
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalWrap *) {
|
||||
return IrInstructionIdOptionalWrap;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapPayload *) {
|
||||
@ -1571,7 +1571,7 @@ static IrInstruction *ir_build_test_nonnull_from(IrBuilder *irb, IrInstruction *
|
||||
static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,
|
||||
bool safety_check_on)
|
||||
{
|
||||
IrInstructionUnwrapMaybe *instruction = ir_build_instruction<IrInstructionUnwrapMaybe>(irb, scope, source_node);
|
||||
IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node);
|
||||
instruction->value = value;
|
||||
instruction->safety_check_on = safety_check_on;
|
||||
|
||||
@ -1590,7 +1590,7 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction *
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_maybe_wrap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
|
||||
IrInstructionMaybeWrap *instruction = ir_build_instruction<IrInstructionMaybeWrap>(irb, scope, source_node);
|
||||
IrInstructionOptionalWrap *instruction = ir_build_instruction<IrInstructionOptionalWrap>(irb, scope, source_node);
|
||||
instruction->value = value;
|
||||
|
||||
ir_ref_instruction(value, irb->current_basic_block);
|
||||
@ -2496,9 +2496,9 @@ static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *s
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstructionErrorReturnTrace::Nullable nullable) {
|
||||
static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstructionErrorReturnTrace::Optional optional) {
|
||||
IrInstructionErrorReturnTrace *instruction = ir_build_instruction<IrInstructionErrorReturnTrace>(irb, scope, source_node);
|
||||
instruction->nullable = nullable;
|
||||
instruction->optional = optional;
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
@ -3295,9 +3295,9 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
|
||||
is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null);
|
||||
}
|
||||
|
||||
IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "MaybeNonNull");
|
||||
IrBasicBlock *null_block = ir_create_basic_block(irb, parent_scope, "MaybeNull");
|
||||
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "MaybeEnd");
|
||||
IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull");
|
||||
IrBasicBlock *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull");
|
||||
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd");
|
||||
ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, null_block);
|
||||
@ -3426,7 +3426,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
|
||||
return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult);
|
||||
case BinOpTypeMergeErrorSets:
|
||||
return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
|
||||
case BinOpTypeUnwrapMaybe:
|
||||
case BinOpTypeUnwrapOptional:
|
||||
return ir_gen_maybe_ok_or(irb, scope, node);
|
||||
case BinOpTypeErrorUnion:
|
||||
return ir_gen_error_union(irb, scope, node);
|
||||
@ -4703,9 +4703,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);
|
||||
case PrefixOpNegationWrap:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);
|
||||
case PrefixOpMaybe:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval);
|
||||
case PrefixOpUnwrapMaybe:
|
||||
case PrefixOpOptional:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval);
|
||||
case PrefixOpUnwrapOptional:
|
||||
return ir_gen_maybe_assert_ok(irb, scope, node, lval);
|
||||
case PrefixOpAddrOf: {
|
||||
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
@ -5370,9 +5370,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
|
||||
IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr);
|
||||
IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val);
|
||||
|
||||
IrBasicBlock *then_block = ir_create_basic_block(irb, scope, "MaybeThen");
|
||||
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "MaybeElse");
|
||||
IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "MaybeEndIf");
|
||||
IrBasicBlock *then_block = ir_create_basic_block(irb, scope, "OptionalThen");
|
||||
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "OptionalElse");
|
||||
IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "OptionalEndIf");
|
||||
|
||||
IrInstruction *is_comptime;
|
||||
if (ir_should_inline(irb->exec, scope)) {
|
||||
@ -7519,7 +7519,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
|
||||
}
|
||||
} else if (const_val_fits_in_num_lit(const_val, other_type)) {
|
||||
return true;
|
||||
} else if (other_type->id == TypeTableEntryIdMaybe) {
|
||||
} else if (other_type->id == TypeTableEntryIdOptional) {
|
||||
TypeTableEntry *child_type = other_type->data.maybe.child_type;
|
||||
if (const_val_fits_in_num_lit(const_val, child_type)) {
|
||||
return true;
|
||||
@ -7663,7 +7663,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
|
||||
return result;
|
||||
|
||||
// * and [*] can do a const-cast-only to ?* and ?[*], respectively
|
||||
if (expected_type->id == TypeTableEntryIdMaybe &&
|
||||
if (expected_type->id == TypeTableEntryIdOptional &&
|
||||
expected_type->data.maybe.child_type->id == TypeTableEntryIdPointer &&
|
||||
actual_type->id == TypeTableEntryIdPointer)
|
||||
{
|
||||
@ -7718,12 +7718,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
|
||||
}
|
||||
|
||||
// maybe
|
||||
if (expected_type->id == TypeTableEntryIdMaybe && actual_type->id == TypeTableEntryIdMaybe) {
|
||||
if (expected_type->id == TypeTableEntryIdOptional && actual_type->id == TypeTableEntryIdOptional) {
|
||||
ConstCastOnly child = types_match_const_cast_only(ira, expected_type->data.maybe.child_type, actual_type->data.maybe.child_type, source_node);
|
||||
if (child.id != ConstCastResultIdOk) {
|
||||
result.id = ConstCastResultIdNullableChild;
|
||||
result.data.nullable_child = allocate_nonzero<ConstCastOnly>(1);
|
||||
*result.data.nullable_child = child;
|
||||
result.id = ConstCastResultIdOptionalChild;
|
||||
result.data.optional_child = allocate_nonzero<ConstCastOnly>(1);
|
||||
*result.data.optional_child = child;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -7925,7 +7925,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
||||
}
|
||||
|
||||
// implicit conversion from ?T to ?U
|
||||
if (expected_type->id == TypeTableEntryIdMaybe && actual_type->id == TypeTableEntryIdMaybe) {
|
||||
if (expected_type->id == TypeTableEntryIdOptional && actual_type->id == TypeTableEntryIdOptional) {
|
||||
ImplicitCastMatchResult res = ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type,
|
||||
actual_type->data.maybe.child_type, value);
|
||||
if (res != ImplicitCastMatchResultNo)
|
||||
@ -7933,7 +7933,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
||||
}
|
||||
|
||||
// implicit conversion from non maybe type to maybe type
|
||||
if (expected_type->id == TypeTableEntryIdMaybe) {
|
||||
if (expected_type->id == TypeTableEntryIdOptional) {
|
||||
ImplicitCastMatchResult res = ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type,
|
||||
actual_type, value);
|
||||
if (res != ImplicitCastMatchResultNo)
|
||||
@ -7941,7 +7941,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
||||
}
|
||||
|
||||
// implicit conversion from null literal to maybe type
|
||||
if (expected_type->id == TypeTableEntryIdMaybe &&
|
||||
if (expected_type->id == TypeTableEntryIdOptional &&
|
||||
actual_type->id == TypeTableEntryIdNull)
|
||||
{
|
||||
return ImplicitCastMatchResultYes;
|
||||
@ -7963,7 +7963,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
||||
|
||||
// implicit conversion from T to U!?T
|
||||
if (expected_type->id == TypeTableEntryIdErrorUnion &&
|
||||
expected_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe &&
|
||||
expected_type->data.error_union.payload_type->id == TypeTableEntryIdOptional &&
|
||||
ir_types_match_with_implicit_cast(ira,
|
||||
expected_type->data.error_union.payload_type->data.maybe.child_type,
|
||||
actual_type, value))
|
||||
@ -8072,7 +8072,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
||||
}
|
||||
|
||||
// implicit [N]T to ?[]const T
|
||||
if (expected_type->id == TypeTableEntryIdMaybe &&
|
||||
if (expected_type->id == TypeTableEntryIdOptional &&
|
||||
is_slice(expected_type->data.maybe.child_type) &&
|
||||
actual_type->id == TypeTableEntryIdArray)
|
||||
{
|
||||
@ -8552,13 +8552,13 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev_type->id == TypeTableEntryIdMaybe &&
|
||||
if (prev_type->id == TypeTableEntryIdOptional &&
|
||||
types_match_const_cast_only(ira, prev_type->data.maybe.child_type, cur_type, source_node).id == ConstCastResultIdOk)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cur_type->id == TypeTableEntryIdMaybe &&
|
||||
if (cur_type->id == TypeTableEntryIdOptional &&
|
||||
types_match_const_cast_only(ira, cur_type->data.maybe.child_type, prev_type, source_node).id == ConstCastResultIdOk)
|
||||
{
|
||||
prev_inst = cur_inst;
|
||||
@ -8711,7 +8711,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
||||
ir_add_error_node(ira, source_node,
|
||||
buf_sprintf("unable to make maybe out of number literal"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (prev_inst->value.type->id == TypeTableEntryIdMaybe) {
|
||||
} else if (prev_inst->value.type->id == TypeTableEntryIdOptional) {
|
||||
return prev_inst->value.type;
|
||||
} else {
|
||||
return get_maybe_type(ira->codegen, prev_inst->value.type);
|
||||
@ -9193,7 +9193,7 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
|
||||
assert(wanted_type->id == TypeTableEntryIdMaybe);
|
||||
assert(wanted_type->id == TypeTableEntryIdOptional);
|
||||
|
||||
if (instr_is_comptime(value)) {
|
||||
TypeTableEntry *payload_type = wanted_type->data.maybe.child_type;
|
||||
@ -9211,7 +9211,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
|
||||
if (get_codegen_ptr_type(wanted_type) != nullptr) {
|
||||
copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
|
||||
} else {
|
||||
const_instruction->base.value.data.x_nullable = val;
|
||||
const_instruction->base.value.data.x_optional = val;
|
||||
}
|
||||
const_instruction->base.value.type = wanted_type;
|
||||
return &const_instruction->base;
|
||||
@ -9219,7 +9219,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
|
||||
|
||||
IrInstruction *result = ir_build_maybe_wrap(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
|
||||
result->value.type = wanted_type;
|
||||
result->value.data.rh_maybe = RuntimeHintMaybeNonNull;
|
||||
result->value.data.rh_maybe = RuntimeHintOptionalNonNull;
|
||||
ir_add_alloca(ira, result, wanted_type);
|
||||
return result;
|
||||
}
|
||||
@ -9361,7 +9361,7 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
|
||||
assert(wanted_type->id == TypeTableEntryIdMaybe);
|
||||
assert(wanted_type->id == TypeTableEntryIdOptional);
|
||||
assert(instr_is_comptime(value));
|
||||
|
||||
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
|
||||
@ -9373,7 +9373,7 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
|
||||
const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
|
||||
const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;
|
||||
} else {
|
||||
const_instruction->base.value.data.x_nullable = nullptr;
|
||||
const_instruction->base.value.data.x_optional = nullptr;
|
||||
}
|
||||
const_instruction->base.value.type = wanted_type;
|
||||
return &const_instruction->base;
|
||||
@ -9992,7 +9992,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
}
|
||||
|
||||
// explicit cast from [N]T to ?[]const N
|
||||
if (wanted_type->id == TypeTableEntryIdMaybe &&
|
||||
if (wanted_type->id == TypeTableEntryIdOptional &&
|
||||
is_slice(wanted_type->data.maybe.child_type) &&
|
||||
actual_type->id == TypeTableEntryIdArray)
|
||||
{
|
||||
@ -10091,7 +10091,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
|
||||
// explicit cast from T to ?T
|
||||
// note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
|
||||
if (wanted_type->id == TypeTableEntryIdMaybe) {
|
||||
if (wanted_type->id == TypeTableEntryIdOptional) {
|
||||
TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type;
|
||||
if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk) {
|
||||
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
|
||||
@ -10120,7 +10120,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
}
|
||||
|
||||
// explicit cast from null literal to maybe type
|
||||
if (wanted_type->id == TypeTableEntryIdMaybe &&
|
||||
if (wanted_type->id == TypeTableEntryIdOptional &&
|
||||
actual_type->id == TypeTableEntryIdNull)
|
||||
{
|
||||
return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
|
||||
@ -10173,8 +10173,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
|
||||
// explicit cast from T to E!?T
|
||||
if (wanted_type->id == TypeTableEntryIdErrorUnion &&
|
||||
wanted_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe &&
|
||||
actual_type->id != TypeTableEntryIdMaybe)
|
||||
wanted_type->data.error_union.payload_type->id == TypeTableEntryIdOptional &&
|
||||
actual_type->id != TypeTableEntryIdOptional)
|
||||
{
|
||||
TypeTableEntry *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
|
||||
if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk ||
|
||||
@ -10737,13 +10737,13 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool nullable_value_is_null(ConstExprValue *val) {
|
||||
static bool optional_value_is_null(ConstExprValue *val) {
|
||||
assert(val->special == ConstValSpecialStatic);
|
||||
if (get_codegen_ptr_type(val->type) != nullptr) {
|
||||
return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
|
||||
val->data.x_ptr.data.hard_coded_addr.addr == 0;
|
||||
} else {
|
||||
return val->data.x_nullable == nullptr;
|
||||
return val->data.x_optional == nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10755,8 +10755,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
|
||||
IrBinOp op_id = bin_op_instruction->op_id;
|
||||
bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
|
||||
if (is_equality_cmp &&
|
||||
((op1->value.type->id == TypeTableEntryIdNull && op2->value.type->id == TypeTableEntryIdMaybe) ||
|
||||
(op2->value.type->id == TypeTableEntryIdNull && op1->value.type->id == TypeTableEntryIdMaybe) ||
|
||||
((op1->value.type->id == TypeTableEntryIdNull && op2->value.type->id == TypeTableEntryIdOptional) ||
|
||||
(op2->value.type->id == TypeTableEntryIdNull && op1->value.type->id == TypeTableEntryIdOptional) ||
|
||||
(op1->value.type->id == TypeTableEntryIdNull && op2->value.type->id == TypeTableEntryIdNull)))
|
||||
{
|
||||
if (op1->value.type->id == TypeTableEntryIdNull && op2->value.type->id == TypeTableEntryIdNull) {
|
||||
@ -10776,7 +10776,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
|
||||
ConstExprValue *maybe_val = ir_resolve_const(ira, maybe_op, UndefBad);
|
||||
if (!maybe_val)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
bool is_null = nullable_value_is_null(maybe_val);
|
||||
bool is_null = optional_value_is_null(maybe_val);
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
|
||||
out_val->data.x_bool = (op_id == IrBinOpCmpEq) ? is_null : !is_null;
|
||||
return ira->codegen->builtin_types.entry_bool;
|
||||
@ -10925,7 +10925,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdUnion:
|
||||
ir_add_error_node(ira, source_node,
|
||||
@ -11998,7 +11998,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdNamespace:
|
||||
@ -12022,7 +12022,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
|
||||
@ -12049,24 +12049,24 @@ static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) {
|
||||
static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
|
||||
IrInstructionErrorReturnTrace *instruction)
|
||||
{
|
||||
if (instruction->nullable == IrInstructionErrorReturnTrace::Null) {
|
||||
if (instruction->optional == IrInstructionErrorReturnTrace::Null) {
|
||||
TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen);
|
||||
TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type);
|
||||
TypeTableEntry *optional_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type);
|
||||
if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) {
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
|
||||
assert(get_codegen_ptr_type(nullable_type) != nullptr);
|
||||
assert(get_codegen_ptr_type(optional_type) != nullptr);
|
||||
out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
|
||||
out_val->data.x_ptr.data.hard_coded_addr.addr = 0;
|
||||
return nullable_type;
|
||||
return optional_type;
|
||||
}
|
||||
IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, instruction->nullable);
|
||||
instruction->base.source_node, instruction->optional);
|
||||
ir_link_new_instruction(new_instruction, &instruction->base);
|
||||
return nullable_type;
|
||||
return optional_type;
|
||||
} else {
|
||||
assert(ira->codegen->have_err_ret_tracing);
|
||||
IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, instruction->nullable);
|
||||
instruction->base.source_node, instruction->optional);
|
||||
ir_link_new_instruction(new_instruction, &instruction->base);
|
||||
return get_ptr_to_stack_trace_type(ira->codegen);
|
||||
}
|
||||
@ -12998,7 +12998,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -13017,7 +13017,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error_node(ira, un_op_instruction->base.source_node,
|
||||
buf_sprintf("type '%s' not nullable", buf_ptr(&type_entry->name)));
|
||||
buf_sprintf("type '%s' not optional", buf_ptr(&type_entry->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -13109,7 +13109,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
|
||||
return ir_analyze_negation(ira, un_op_instruction);
|
||||
case IrUnOpDereference:
|
||||
return ir_analyze_dereference(ira, un_op_instruction);
|
||||
case IrUnOpMaybe:
|
||||
case IrUnOpOptional:
|
||||
return ir_analyze_maybe(ira, un_op_instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -14155,7 +14155,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
|
||||
buf_ptr(&child_type->name), buf_ptr(field_name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
} else if (child_type->id == TypeTableEntryIdMaybe) {
|
||||
} else if (child_type->id == TypeTableEntryIdOptional) {
|
||||
if (buf_eql_str(field_name, "Child")) {
|
||||
bool ptr_is_const = true;
|
||||
bool ptr_is_volatile = false;
|
||||
@ -14339,7 +14339,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -14607,7 +14607,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -14715,7 +14715,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -14786,7 +14786,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -14810,14 +14810,14 @@ static TypeTableEntry *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIn
|
||||
|
||||
TypeTableEntry *type_entry = value->value.type;
|
||||
|
||||
if (type_entry->id == TypeTableEntryIdMaybe) {
|
||||
if (type_entry->id == TypeTableEntryIdOptional) {
|
||||
if (instr_is_comptime(value)) {
|
||||
ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefBad);
|
||||
if (!maybe_val)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
|
||||
out_val->data.x_bool = !nullable_value_is_null(maybe_val);
|
||||
out_val->data.x_bool = !optional_value_is_null(maybe_val);
|
||||
return ira->codegen->builtin_types.entry_bool;
|
||||
}
|
||||
|
||||
@ -14835,7 +14835,7 @@ static TypeTableEntry *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIn
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
|
||||
IrInstructionUnwrapMaybe *unwrap_maybe_instruction)
|
||||
IrInstructionUnwrapOptional *unwrap_maybe_instruction)
|
||||
{
|
||||
IrInstruction *value = unwrap_maybe_instruction->value->other;
|
||||
if (type_is_invalid(value->value.type))
|
||||
@ -14863,9 +14863,9 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile);
|
||||
ir_link_new_instruction(result_instr, &unwrap_maybe_instruction->base);
|
||||
return result_instr->value.type;
|
||||
} else if (type_entry->id != TypeTableEntryIdMaybe) {
|
||||
} else if (type_entry->id != TypeTableEntryIdOptional) {
|
||||
ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,
|
||||
buf_sprintf("expected nullable type, found '%s'", buf_ptr(&type_entry->name)));
|
||||
buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
@ -14881,7 +14881,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
|
||||
ConstExprValue *maybe_val = const_ptr_pointee(ira->codegen, val);
|
||||
|
||||
if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
|
||||
if (nullable_value_is_null(maybe_val)) {
|
||||
if (optional_value_is_null(maybe_val)) {
|
||||
ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
@ -14891,7 +14891,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
|
||||
if (type_is_codegen_pointer(child_type)) {
|
||||
out_val->data.x_ptr.data.ref.pointee = maybe_val;
|
||||
} else {
|
||||
out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_nullable;
|
||||
out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
|
||||
}
|
||||
return result_type;
|
||||
}
|
||||
@ -15216,7 +15216,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
@ -15737,7 +15737,7 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdUnion:
|
||||
@ -16255,11 +16255,11 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
|
||||
0, 0);
|
||||
fn_def_fields[6].type = get_maybe_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
|
||||
if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
|
||||
fn_def_fields[6].data.x_nullable = create_const_vals(1);
|
||||
fn_def_fields[6].data.x_optional = create_const_vals(1);
|
||||
ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
|
||||
init_const_slice(ira->codegen, fn_def_fields[6].data.x_nullable, lib_name, 0, buf_len(fn_node->lib_name), true);
|
||||
init_const_slice(ira->codegen, fn_def_fields[6].data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true);
|
||||
} else {
|
||||
fn_def_fields[6].data.x_nullable = nullptr;
|
||||
fn_def_fields[6].data.x_optional = nullptr;
|
||||
}
|
||||
// return_type: type
|
||||
ensure_field_index(fn_def_val->type, "return_type", 7);
|
||||
@ -16507,11 +16507,11 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
|
||||
|
||||
break;
|
||||
}
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
{
|
||||
result = create_const_vals(1);
|
||||
result->special = ConstValSpecialStatic;
|
||||
result->type = ir_type_info_get_type(ira, "Nullable");
|
||||
result->type = ir_type_info_get_type(ira, "Optional");
|
||||
|
||||
ConstExprValue *fields = create_const_vals(1);
|
||||
result->data.x_struct.fields = fields;
|
||||
@ -16725,10 +16725,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
|
||||
inner_fields[1].type = get_maybe_type(ira->codegen, type_info_enum_field_type);
|
||||
|
||||
if (fields[1].data.x_type == ira->codegen->builtin_types.entry_undef) {
|
||||
inner_fields[1].data.x_nullable = nullptr;
|
||||
inner_fields[1].data.x_optional = nullptr;
|
||||
} else {
|
||||
inner_fields[1].data.x_nullable = create_const_vals(1);
|
||||
make_enum_field_val(inner_fields[1].data.x_nullable, union_field->enum_field, type_info_enum_field_type);
|
||||
inner_fields[1].data.x_optional = create_const_vals(1);
|
||||
make_enum_field_val(inner_fields[1].data.x_optional, union_field->enum_field, type_info_enum_field_type);
|
||||
}
|
||||
|
||||
inner_fields[2].special = ConstValSpecialStatic;
|
||||
@ -16796,13 +16796,13 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
|
||||
inner_fields[1].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_usize);
|
||||
|
||||
if (!type_has_bits(struct_field->type_entry)) {
|
||||
inner_fields[1].data.x_nullable = nullptr;
|
||||
inner_fields[1].data.x_optional = nullptr;
|
||||
} else {
|
||||
size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index);
|
||||
inner_fields[1].data.x_nullable = create_const_vals(1);
|
||||
inner_fields[1].data.x_nullable->special = ConstValSpecialStatic;
|
||||
inner_fields[1].data.x_nullable->type = ira->codegen->builtin_types.entry_usize;
|
||||
bigint_init_unsigned(&inner_fields[1].data.x_nullable->data.x_bigint, byte_offset);
|
||||
inner_fields[1].data.x_optional = create_const_vals(1);
|
||||
inner_fields[1].data.x_optional->special = ConstValSpecialStatic;
|
||||
inner_fields[1].data.x_optional->type = ira->codegen->builtin_types.entry_usize;
|
||||
bigint_init_unsigned(&inner_fields[1].data.x_optional->data.x_bigint, byte_offset);
|
||||
}
|
||||
|
||||
inner_fields[2].special = ConstValSpecialStatic;
|
||||
@ -18027,7 +18027,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
|
||||
case TypeTableEntryIdPromise:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -18591,7 +18591,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
|
||||
old_align_bytes = fn_type_id.alignment;
|
||||
fn_type_id.alignment = align_bytes;
|
||||
result_type = get_fn_type(ira->codegen, &fn_type_id);
|
||||
} else if (target_type->id == TypeTableEntryIdMaybe &&
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdPointer)
|
||||
{
|
||||
TypeTableEntry *ptr_type = target_type->data.maybe.child_type;
|
||||
@ -18599,7 +18599,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
|
||||
TypeTableEntry *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes);
|
||||
|
||||
result_type = get_maybe_type(ira->codegen, better_ptr_type);
|
||||
} else if (target_type->id == TypeTableEntryIdMaybe &&
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdFn)
|
||||
{
|
||||
FnTypeId fn_type_id = target_type->data.maybe.child_type->data.fn.fn_type_id;
|
||||
@ -18757,7 +18757,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
||||
return;
|
||||
case TypeTableEntryIdStruct:
|
||||
zig_panic("TODO buf_write_value_bytes struct type");
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
zig_panic("TODO buf_write_value_bytes maybe type");
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
zig_panic("TODO buf_write_value_bytes error union");
|
||||
@ -18815,7 +18815,7 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
||||
zig_panic("TODO buf_read_value_bytes array type");
|
||||
case TypeTableEntryIdStruct:
|
||||
zig_panic("TODO buf_read_value_bytes struct type");
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdOptional:
|
||||
zig_panic("TODO buf_read_value_bytes maybe type");
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
zig_panic("TODO buf_read_value_bytes error union");
|
||||
@ -19731,7 +19731,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
||||
case IrInstructionIdUnionInit:
|
||||
case IrInstructionIdStructFieldPtr:
|
||||
case IrInstructionIdUnionFieldPtr:
|
||||
case IrInstructionIdMaybeWrap:
|
||||
case IrInstructionIdOptionalWrap:
|
||||
case IrInstructionIdErrWrapCode:
|
||||
case IrInstructionIdErrWrapPayload:
|
||||
case IrInstructionIdCast:
|
||||
@ -19791,8 +19791,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
||||
return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
|
||||
case IrInstructionIdTestNonNull:
|
||||
return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
|
||||
case IrInstructionIdUnwrapMaybe:
|
||||
return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapMaybe *)instruction);
|
||||
case IrInstructionIdUnwrapOptional:
|
||||
return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);
|
||||
case IrInstructionIdClz:
|
||||
return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
|
||||
case IrInstructionIdCtz:
|
||||
@ -20128,7 +20128,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
case IrInstructionIdSliceType:
|
||||
case IrInstructionIdSizeOf:
|
||||
case IrInstructionIdTestNonNull:
|
||||
case IrInstructionIdUnwrapMaybe:
|
||||
case IrInstructionIdUnwrapOptional:
|
||||
case IrInstructionIdClz:
|
||||
case IrInstructionIdCtz:
|
||||
case IrInstructionIdSwitchVar:
|
||||
@ -20150,7 +20150,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
case IrInstructionIdFrameAddress:
|
||||
case IrInstructionIdTestErr:
|
||||
case IrInstructionIdUnwrapErrCode:
|
||||
case IrInstructionIdMaybeWrap:
|
||||
case IrInstructionIdOptionalWrap:
|
||||
case IrInstructionIdErrWrapCode:
|
||||
case IrInstructionIdErrWrapPayload:
|
||||
case IrInstructionIdFnProto:
|
||||
|
||||
@ -148,7 +148,7 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
|
||||
return "-%";
|
||||
case IrUnOpDereference:
|
||||
return "*";
|
||||
case IrUnOpMaybe:
|
||||
case IrUnOpOptional:
|
||||
return "?";
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -481,7 +481,7 @@ static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instructi
|
||||
fprintf(irp->f, " != null");
|
||||
}
|
||||
|
||||
static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapMaybe *instruction) {
|
||||
static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {
|
||||
fprintf(irp->f, "&??*");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
if (!instruction->safety_check_on) {
|
||||
@ -777,7 +777,7 @@ static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayl
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionMaybeWrap *instruction) {
|
||||
static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
|
||||
fprintf(irp->f, "@maybeWrap(");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, ")");
|
||||
@ -1032,7 +1032,7 @@ static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) {
|
||||
|
||||
static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTrace *instruction) {
|
||||
fprintf(irp->f, "@errorReturnTrace(");
|
||||
switch (instruction->nullable) {
|
||||
switch (instruction->optional) {
|
||||
case IrInstructionErrorReturnTrace::Null:
|
||||
fprintf(irp->f, "Null");
|
||||
break;
|
||||
@ -1348,8 +1348,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdTestNonNull:
|
||||
ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);
|
||||
break;
|
||||
case IrInstructionIdUnwrapMaybe:
|
||||
ir_print_unwrap_maybe(irp, (IrInstructionUnwrapMaybe *)instruction);
|
||||
case IrInstructionIdUnwrapOptional:
|
||||
ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCtz:
|
||||
ir_print_ctz(irp, (IrInstructionCtz *)instruction);
|
||||
@ -1465,8 +1465,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdUnwrapErrPayload:
|
||||
ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction);
|
||||
break;
|
||||
case IrInstructionIdMaybeWrap:
|
||||
ir_print_maybe_wrap(irp, (IrInstructionMaybeWrap *)instruction);
|
||||
case IrInstructionIdOptionalWrap:
|
||||
ir_print_maybe_wrap(irp, (IrInstructionOptionalWrap *)instruction);
|
||||
break;
|
||||
case IrInstructionIdErrWrapCode:
|
||||
ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction);
|
||||
|
||||
@ -1046,12 +1046,11 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index
|
||||
}
|
||||
|
||||
/*
|
||||
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | PtrDerefExpression | SliceExpression)
|
||||
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ".*" | ".?")
|
||||
FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
|
||||
ArrayAccessExpression : token(LBracket) Expression token(RBracket)
|
||||
SliceExpression = "[" Expression ".." option(Expression) "]"
|
||||
FieldAccessExpression : token(Dot) token(Symbol)
|
||||
PtrDerefExpression = ".*"
|
||||
StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
|
||||
*/
|
||||
static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
@ -1148,6 +1147,14 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
|
||||
AstNode *node = ast_create_node(pc, NodeTypePtrDeref, first_token);
|
||||
node->data.ptr_deref_expr.target = primary_expr;
|
||||
|
||||
primary_expr = node;
|
||||
} else if (token->id == TokenIdQuestion) {
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, first_token);
|
||||
node->data.prefix_op_expr.prefix_op = PrefixOpUnwrapOptional;
|
||||
node->data.prefix_op_expr.primary_expr = primary_expr;
|
||||
|
||||
primary_expr = node;
|
||||
} else {
|
||||
ast_invalid_token_error(pc, token);
|
||||
@ -1165,8 +1172,8 @@ static PrefixOp tok_to_prefix_op(Token *token) {
|
||||
case TokenIdDash: return PrefixOpNegation;
|
||||
case TokenIdMinusPercent: return PrefixOpNegationWrap;
|
||||
case TokenIdTilde: return PrefixOpBinNot;
|
||||
case TokenIdMaybe: return PrefixOpMaybe;
|
||||
case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
|
||||
case TokenIdQuestion: return PrefixOpOptional;
|
||||
case TokenIdDoubleQuestion: return PrefixOpUnwrapOptional;
|
||||
case TokenIdAmpersand: return PrefixOpAddrOf;
|
||||
default: return PrefixOpInvalid;
|
||||
}
|
||||
@ -2304,8 +2311,8 @@ static BinOpType ast_parse_ass_op(ParseContext *pc, size_t *token_index, bool ma
|
||||
}
|
||||
|
||||
/*
|
||||
UnwrapExpression : BoolOrExpression (UnwrapMaybe | UnwrapError) | BoolOrExpression
|
||||
UnwrapMaybe : "??" BoolOrExpression
|
||||
UnwrapExpression : BoolOrExpression (UnwrapOptional | UnwrapError) | BoolOrExpression
|
||||
UnwrapOptional : "??" BoolOrExpression
|
||||
UnwrapError = "catch" option("|" Symbol "|") Expression
|
||||
*/
|
||||
static AstNode *ast_parse_unwrap_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
@ -2322,7 +2329,7 @@ static AstNode *ast_parse_unwrap_expr(ParseContext *pc, size_t *token_index, boo
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = lhs;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeUnwrapMaybe;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeUnwrapOptional;
|
||||
node->data.bin_op_expr.op2 = rhs;
|
||||
|
||||
return node;
|
||||
|
||||
@ -625,7 +625,7 @@ void tokenize(Buf *buf, Tokenization *out) {
|
||||
t.state = TokenizeStateSawDot;
|
||||
break;
|
||||
case '?':
|
||||
begin_token(&t, TokenIdMaybe);
|
||||
begin_token(&t, TokenIdQuestion);
|
||||
t.state = TokenizeStateSawQuestionMark;
|
||||
break;
|
||||
default:
|
||||
@ -639,11 +639,6 @@ void tokenize(Buf *buf, Tokenization *out) {
|
||||
end_token(&t);
|
||||
t.state = TokenizeStateStart;
|
||||
break;
|
||||
case '=':
|
||||
set_token_id(&t, t.cur_tok, TokenIdMaybeAssign);
|
||||
end_token(&t);
|
||||
t.state = TokenizeStateStart;
|
||||
break;
|
||||
default:
|
||||
t.pos -= 1;
|
||||
end_token(&t);
|
||||
@ -1609,8 +1604,7 @@ const char * token_name(TokenId id) {
|
||||
case TokenIdLBrace: return "{";
|
||||
case TokenIdLBracket: return "[";
|
||||
case TokenIdLParen: return "(";
|
||||
case TokenIdMaybe: return "?";
|
||||
case TokenIdMaybeAssign: return "?=";
|
||||
case TokenIdQuestion: return "?";
|
||||
case TokenIdMinusEq: return "-=";
|
||||
case TokenIdMinusPercent: return "-%";
|
||||
case TokenIdMinusPercentEq: return "-%=";
|
||||
|
||||
@ -100,8 +100,7 @@ enum TokenId {
|
||||
TokenIdLBrace,
|
||||
TokenIdLBracket,
|
||||
TokenIdLParen,
|
||||
TokenIdMaybe,
|
||||
TokenIdMaybeAssign,
|
||||
TokenIdQuestion,
|
||||
TokenIdMinusEq,
|
||||
TokenIdMinusPercent,
|
||||
TokenIdMinusPercentEq,
|
||||
|
||||
@ -382,7 +382,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r
|
||||
fn_def->data.fn_def.fn_proto = fn_proto;
|
||||
fn_proto->data.fn_proto.fn_def_node = fn_def;
|
||||
|
||||
AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, ref_node);
|
||||
AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapOptional, ref_node);
|
||||
AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr);
|
||||
fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
|
||||
|
||||
@ -410,7 +410,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r
|
||||
}
|
||||
|
||||
static AstNode *trans_create_node_unwrap_null(Context *c, AstNode *child) {
|
||||
return trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, child);
|
||||
return trans_create_node_prefix_op(c, PrefixOpUnwrapOptional, child);
|
||||
}
|
||||
|
||||
static AstNode *get_global(Context *c, Buf *name) {
|
||||
@ -879,14 +879,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
|
||||
}
|
||||
|
||||
if (qual_type_child_is_fn_proto(child_qt)) {
|
||||
return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node);
|
||||
return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
|
||||
}
|
||||
|
||||
PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;
|
||||
|
||||
AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
|
||||
child_qt.isVolatileQualified(), child_node, ptr_len);
|
||||
return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node);
|
||||
return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
|
||||
}
|
||||
case Type::Typedef:
|
||||
{
|
||||
@ -1963,7 +1963,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
|
||||
bool is_fn_ptr = qual_type_is_fn_ptr(stmt->getSubExpr()->getType());
|
||||
if (is_fn_ptr)
|
||||
return value_node;
|
||||
AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node);
|
||||
AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapOptional, value_node);
|
||||
return trans_create_node_ptr_deref(c, unwrapped);
|
||||
}
|
||||
case UO_Plus:
|
||||
@ -2587,7 +2587,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
|
||||
}
|
||||
}
|
||||
if (callee_node == nullptr) {
|
||||
callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node);
|
||||
callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapOptional, callee_raw_node);
|
||||
}
|
||||
} else {
|
||||
callee_node = callee_raw_node;
|
||||
@ -4301,7 +4301,7 @@ static AstNode *trans_lookup_ast_maybe_fn(Context *c, AstNode *ref_node) {
|
||||
return nullptr;
|
||||
if (prefix_node->type != NodeTypePrefixOpExpr)
|
||||
return nullptr;
|
||||
if (prefix_node->data.prefix_op_expr.prefix_op != PrefixOpMaybe)
|
||||
if (prefix_node->data.prefix_op_expr.prefix_op != PrefixOpOptional)
|
||||
return nullptr;
|
||||
|
||||
AstNode *fn_proto_node = prefix_node->data.prefix_op_expr.primary_expr;
|
||||
|
||||
@ -258,7 +258,7 @@ test "iterator ArrayList test" {
|
||||
}
|
||||
|
||||
it.reset();
|
||||
assert(??it.next() == 1);
|
||||
assert(it.next().? == 1);
|
||||
}
|
||||
|
||||
test "insert ArrayList test" {
|
||||
|
||||
@ -72,15 +72,15 @@ test "BufMap" {
|
||||
defer bufmap.deinit();
|
||||
|
||||
try bufmap.set("x", "1");
|
||||
assert(mem.eql(u8, ??bufmap.get("x"), "1"));
|
||||
assert(mem.eql(u8, bufmap.get("x").?, "1"));
|
||||
assert(1 == bufmap.count());
|
||||
|
||||
try bufmap.set("x", "2");
|
||||
assert(mem.eql(u8, ??bufmap.get("x"), "2"));
|
||||
assert(mem.eql(u8, bufmap.get("x").?, "2"));
|
||||
assert(1 == bufmap.count());
|
||||
|
||||
try bufmap.set("x", "3");
|
||||
assert(mem.eql(u8, ??bufmap.get("x"), "3"));
|
||||
assert(mem.eql(u8, bufmap.get("x").?, "3"));
|
||||
assert(1 == bufmap.count());
|
||||
|
||||
bufmap.delete("x");
|
||||
|
||||
@ -40,9 +40,9 @@ pub const TcpServer = struct {
|
||||
self.listen_address = std.net.Address.initPosix(try std.os.posixGetSockName(self.sockfd));
|
||||
|
||||
self.accept_coro = try async<self.loop.allocator> TcpServer.handler(self);
|
||||
errdefer cancel ??self.accept_coro;
|
||||
errdefer cancel self.accept_coro.?;
|
||||
|
||||
try self.loop.addFd(self.sockfd, ??self.accept_coro);
|
||||
try self.loop.addFd(self.sockfd, self.accept_coro.?);
|
||||
errdefer self.loop.removeFd(self.sockfd);
|
||||
}
|
||||
|
||||
|
||||
@ -111,7 +111,7 @@ pub fn formatType(
|
||||
builtin.TypeId.Bool => {
|
||||
return output(context, if (value) "true" else "false");
|
||||
},
|
||||
builtin.TypeId.Nullable => {
|
||||
builtin.TypeId.Optional => {
|
||||
if (value) |payload| {
|
||||
return formatType(payload, fmt, context, Errors, output);
|
||||
} else {
|
||||
@ -819,11 +819,11 @@ test "parse unsigned comptime" {
|
||||
test "fmt.format" {
|
||||
{
|
||||
const value: ?i32 = 1234;
|
||||
try testFmt("nullable: 1234\n", "nullable: {}\n", value);
|
||||
try testFmt("optional: 1234\n", "optional: {}\n", value);
|
||||
}
|
||||
{
|
||||
const value: ?i32 = null;
|
||||
try testFmt("nullable: null\n", "nullable: {}\n", value);
|
||||
try testFmt("optional: null\n", "optional: {}\n", value);
|
||||
}
|
||||
{
|
||||
const value: error!i32 = 1234;
|
||||
|
||||
@ -265,11 +265,11 @@ test "basic hash map usage" {
|
||||
assert((map.put(4, 44) catch unreachable) == null);
|
||||
assert((map.put(5, 55) catch unreachable) == null);
|
||||
|
||||
assert(??(map.put(5, 66) catch unreachable) == 55);
|
||||
assert(??(map.put(5, 55) catch unreachable) == 66);
|
||||
assert((map.put(5, 66) catch unreachable).? == 55);
|
||||
assert((map.put(5, 55) catch unreachable).? == 66);
|
||||
|
||||
assert(map.contains(2));
|
||||
assert((??map.get(2)).value == 22);
|
||||
assert(map.get(2).?.value == 22);
|
||||
_ = map.remove(2);
|
||||
assert(map.remove(2) == null);
|
||||
assert(map.get(2) == null);
|
||||
@ -317,7 +317,7 @@ test "iterator hash map" {
|
||||
}
|
||||
|
||||
it.reset();
|
||||
var entry = ??it.next();
|
||||
var entry = it.next().?;
|
||||
assert(entry.key == keys[0]);
|
||||
assert(entry.value == values[0]);
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ pub const DirectAllocator = struct {
|
||||
const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;
|
||||
const old_ptr = @intToPtr(*c_void, root_addr);
|
||||
const amt = new_size + alignment + @sizeOf(usize);
|
||||
const new_ptr = os.windows.HeapReAlloc(??self.heap_handle, 0, old_ptr, amt) ?? blk: {
|
||||
const new_ptr = os.windows.HeapReAlloc(self.heap_handle.?, 0, old_ptr, amt) ?? blk: {
|
||||
if (new_size > old_mem.len) return error.OutOfMemory;
|
||||
const new_record_addr = old_record_addr - new_size + old_mem.len;
|
||||
@intToPtr(*align(1) usize, new_record_addr).* = root_addr;
|
||||
@ -171,7 +171,7 @@ pub const DirectAllocator = struct {
|
||||
const record_addr = @ptrToInt(bytes.ptr) + bytes.len;
|
||||
const root_addr = @intToPtr(*align(1) usize, record_addr).*;
|
||||
const ptr = @intToPtr(*c_void, root_addr);
|
||||
_ = os.windows.HeapFree(??self.heap_handle, 0, ptr);
|
||||
_ = os.windows.HeapFree(self.heap_handle.?, 0, ptr);
|
||||
},
|
||||
else => @compileError("Unsupported OS"),
|
||||
}
|
||||
|
||||
12
std/json.zig
12
std/json.zig
@ -908,7 +908,7 @@ pub const TokenStream = struct {
|
||||
};
|
||||
|
||||
fn checkNext(p: *TokenStream, id: Token.Id) void {
|
||||
const token = ??(p.next() catch unreachable);
|
||||
const token = (p.next() catch unreachable).?;
|
||||
debug.assert(token.id == id);
|
||||
}
|
||||
|
||||
@ -1376,17 +1376,17 @@ test "json parser dynamic" {
|
||||
|
||||
var root = tree.root;
|
||||
|
||||
var image = (??root.Object.get("Image")).value;
|
||||
var image = root.Object.get("Image").?.value;
|
||||
|
||||
const width = (??image.Object.get("Width")).value;
|
||||
const width = image.Object.get("Width").?.value;
|
||||
debug.assert(width.Integer == 800);
|
||||
|
||||
const height = (??image.Object.get("Height")).value;
|
||||
const height = image.Object.get("Height").?.value;
|
||||
debug.assert(height.Integer == 600);
|
||||
|
||||
const title = (??image.Object.get("Title")).value;
|
||||
const title = image.Object.get("Title").?.value;
|
||||
debug.assert(mem.eql(u8, title.String, "View from 15th Floor"));
|
||||
|
||||
const animated = (??image.Object.get("Animated")).value;
|
||||
const animated = image.Object.get("Animated").?.value;
|
||||
debug.assert(animated.Bool == false);
|
||||
}
|
||||
|
||||
@ -270,8 +270,8 @@ test "basic linked list test" {
|
||||
var last = list.pop(); // {2, 3, 4}
|
||||
list.remove(three); // {2, 4}
|
||||
|
||||
assert((??list.first).data == 2);
|
||||
assert((??list.last).data == 4);
|
||||
assert(list.first.?.data == 2);
|
||||
assert(list.last.?.data == 4);
|
||||
assert(list.len == 2);
|
||||
}
|
||||
|
||||
@ -336,7 +336,7 @@ test "basic intrusive linked list test" {
|
||||
var last = list.pop(); // {2, 3, 4}
|
||||
list.remove(&three.link); // {2, 4}
|
||||
|
||||
assert((??list.first).toData().value == 2);
|
||||
assert((??list.last).toData().value == 4);
|
||||
assert(list.first.?.toData().value == 2);
|
||||
assert(list.last.?.toData().value == 4);
|
||||
assert(list.len == 2);
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ pub fn loadSymbols(allocator: *mem.Allocator, in: *io.FileInStream) !SymbolTable
|
||||
for (syms) |sym| {
|
||||
if (!isSymbol(sym)) continue;
|
||||
const start = sym.n_strx;
|
||||
const end = ??mem.indexOfScalarPos(u8, strings, start, 0);
|
||||
const end = mem.indexOfScalarPos(u8, strings, start, 0).?;
|
||||
const name = strings[start..end];
|
||||
const address = sym.n_value;
|
||||
symbols[nsym] = Symbol{ .name = name, .address = address };
|
||||
|
||||
22
std/mem.zig
22
std/mem.zig
@ -304,20 +304,20 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee
|
||||
}
|
||||
|
||||
test "mem.indexOf" {
|
||||
assert(??indexOf(u8, "one two three four", "four") == 14);
|
||||
assert(??lastIndexOf(u8, "one two three two four", "two") == 14);
|
||||
assert(indexOf(u8, "one two three four", "four").? == 14);
|
||||
assert(lastIndexOf(u8, "one two three two four", "two").? == 14);
|
||||
assert(indexOf(u8, "one two three four", "gour") == null);
|
||||
assert(lastIndexOf(u8, "one two three four", "gour") == null);
|
||||
assert(??indexOf(u8, "foo", "foo") == 0);
|
||||
assert(??lastIndexOf(u8, "foo", "foo") == 0);
|
||||
assert(indexOf(u8, "foo", "foo").? == 0);
|
||||
assert(lastIndexOf(u8, "foo", "foo").? == 0);
|
||||
assert(indexOf(u8, "foo", "fool") == null);
|
||||
assert(lastIndexOf(u8, "foo", "lfoo") == null);
|
||||
assert(lastIndexOf(u8, "foo", "fool") == null);
|
||||
|
||||
assert(??indexOf(u8, "foo foo", "foo") == 0);
|
||||
assert(??lastIndexOf(u8, "foo foo", "foo") == 4);
|
||||
assert(??lastIndexOfAny(u8, "boo, cat", "abo") == 6);
|
||||
assert(??lastIndexOfScalar(u8, "boo", 'o') == 2);
|
||||
assert(indexOf(u8, "foo foo", "foo").? == 0);
|
||||
assert(lastIndexOf(u8, "foo foo", "foo").? == 4);
|
||||
assert(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
|
||||
assert(lastIndexOfScalar(u8, "boo", 'o').? == 2);
|
||||
}
|
||||
|
||||
/// Reads an integer from memory with size equal to bytes.len.
|
||||
@ -432,9 +432,9 @@ pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {
|
||||
|
||||
test "mem.split" {
|
||||
var it = split(" abc def ghi ", " ");
|
||||
assert(eql(u8, ??it.next(), "abc"));
|
||||
assert(eql(u8, ??it.next(), "def"));
|
||||
assert(eql(u8, ??it.next(), "ghi"));
|
||||
assert(eql(u8, it.next().?, "abc"));
|
||||
assert(eql(u8, it.next().?, "def"));
|
||||
assert(eql(u8, it.next().?, "ghi"));
|
||||
assert(it.next() == null);
|
||||
}
|
||||
|
||||
|
||||
@ -156,7 +156,7 @@ pub const ChildProcess = struct {
|
||||
};
|
||||
}
|
||||
try self.waitUnwrappedWindows();
|
||||
return ??self.term;
|
||||
return self.term.?;
|
||||
}
|
||||
|
||||
pub fn killPosix(self: *ChildProcess) !Term {
|
||||
@ -175,7 +175,7 @@ pub const ChildProcess = struct {
|
||||
};
|
||||
}
|
||||
self.waitUnwrapped();
|
||||
return ??self.term;
|
||||
return self.term.?;
|
||||
}
|
||||
|
||||
/// Blocks until child process terminates and then cleans up all resources.
|
||||
@ -212,8 +212,8 @@ pub const ChildProcess = struct {
|
||||
defer Buffer.deinit(&stdout);
|
||||
defer Buffer.deinit(&stderr);
|
||||
|
||||
var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
|
||||
var stdout_file_in_stream = io.FileInStream.init(&child.stdout.?);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&child.stderr.?);
|
||||
|
||||
try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
|
||||
try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
|
||||
@ -232,7 +232,7 @@ pub const ChildProcess = struct {
|
||||
}
|
||||
|
||||
try self.waitUnwrappedWindows();
|
||||
return ??self.term;
|
||||
return self.term.?;
|
||||
}
|
||||
|
||||
fn waitPosix(self: *ChildProcess) !Term {
|
||||
@ -242,7 +242,7 @@ pub const ChildProcess = struct {
|
||||
}
|
||||
|
||||
self.waitUnwrapped();
|
||||
return ??self.term;
|
||||
return self.term.?;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *ChildProcess) void {
|
||||
@ -619,13 +619,13 @@ pub const ChildProcess = struct {
|
||||
self.term = null;
|
||||
|
||||
if (self.stdin_behavior == StdIo.Pipe) {
|
||||
os.close(??g_hChildStd_IN_Rd);
|
||||
os.close(g_hChildStd_IN_Rd.?);
|
||||
}
|
||||
if (self.stderr_behavior == StdIo.Pipe) {
|
||||
os.close(??g_hChildStd_ERR_Wr);
|
||||
os.close(g_hChildStd_ERR_Wr.?);
|
||||
}
|
||||
if (self.stdout_behavior == StdIo.Pipe) {
|
||||
os.close(??g_hChildStd_OUT_Wr);
|
||||
os.close(g_hChildStd_OUT_Wr.?);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -422,7 +422,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:
|
||||
|
||||
const exe_path = argv[0];
|
||||
if (mem.indexOfScalar(u8, exe_path, '/') != null) {
|
||||
return posixExecveErrnoToErr(posix.getErrno(posix.execve(??argv_buf[0], argv_buf.ptr, envp_buf.ptr)));
|
||||
return posixExecveErrnoToErr(posix.getErrno(posix.execve(argv_buf[0].?, argv_buf.ptr, envp_buf.ptr)));
|
||||
}
|
||||
|
||||
const PATH = getEnvPosix("PATH") ?? "/usr/local/bin:/bin/:/usr/bin";
|
||||
@ -1729,7 +1729,7 @@ test "windows arg parsing" {
|
||||
fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []const u8) void {
|
||||
var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);
|
||||
for (expected_args) |expected_arg| {
|
||||
const arg = ??it.next(debug.global_allocator) catch unreachable;
|
||||
const arg = it.next(debug.global_allocator).? catch unreachable;
|
||||
assert(mem.eql(u8, arg, expected_arg));
|
||||
}
|
||||
assert(it.next(debug.global_allocator) == null);
|
||||
|
||||
@ -67,7 +67,7 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
|
||||
if (0 == syms[i].st_shndx) continue;
|
||||
if (!mem.eql(u8, name, cstr.toSliceConst(strings + syms[i].st_name))) continue;
|
||||
if (maybe_versym) |versym| {
|
||||
if (!checkver(??maybe_verdef, versym[i], vername, strings))
|
||||
if (!checkver(maybe_verdef.?, versym[i], vername, strings))
|
||||
continue;
|
||||
}
|
||||
return base + syms[i].st_value;
|
||||
|
||||
@ -265,7 +265,7 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {
|
||||
var it2 = mem.split(ns2, []u8{sep2});
|
||||
|
||||
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
|
||||
return asciiEqlIgnoreCase(??it1.next(), ??it2.next());
|
||||
return asciiEqlIgnoreCase(it1.next().?, it2.next().?);
|
||||
}
|
||||
|
||||
fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8) bool {
|
||||
@ -286,7 +286,7 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8
|
||||
var it2 = mem.split(p2, []u8{sep2});
|
||||
|
||||
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
|
||||
return asciiEqlIgnoreCase(??it1.next(), ??it2.next()) and asciiEqlIgnoreCase(??it1.next(), ??it2.next());
|
||||
return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?);
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -414,8 +414,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
|
||||
WindowsPath.Kind.NetworkShare => {
|
||||
result = try allocator.alloc(u8, max_size);
|
||||
var it = mem.split(paths[first_index], "/\\");
|
||||
const server_name = ??it.next();
|
||||
const other_name = ??it.next();
|
||||
const server_name = it.next().?;
|
||||
const other_name = it.next().?;
|
||||
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
|
||||
@ -364,7 +364,7 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
|
||||
assert(x == 0);
|
||||
}
|
||||
|
||||
assert(??list.pop() == 100);
|
||||
assert(list.pop().? == 100);
|
||||
assert(list.len == 99);
|
||||
|
||||
try list.pushMany([]i32{
|
||||
@ -373,9 +373,9 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
|
||||
3,
|
||||
});
|
||||
assert(list.len == 102);
|
||||
assert(??list.pop() == 3);
|
||||
assert(??list.pop() == 2);
|
||||
assert(??list.pop() == 1);
|
||||
assert(list.pop().? == 3);
|
||||
assert(list.pop().? == 2);
|
||||
assert(list.pop().? == 1);
|
||||
assert(list.len == 99);
|
||||
|
||||
try list.pushMany([]const i32{});
|
||||
|
||||
@ -54,10 +54,10 @@ fn posixCallMainAndExit() noreturn {
|
||||
const argc = argc_ptr[0];
|
||||
const argv = @ptrCast([*][*]u8, argc_ptr + 1);
|
||||
|
||||
const envp_nullable = @ptrCast([*]?[*]u8, argv + argc + 1);
|
||||
const envp_optional = @ptrCast([*]?[*]u8, argv + argc + 1);
|
||||
var envp_count: usize = 0;
|
||||
while (envp_nullable[envp_count]) |_| : (envp_count += 1) {}
|
||||
const envp = @ptrCast([*][*]u8, envp_nullable)[0..envp_count];
|
||||
while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
|
||||
const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];
|
||||
if (builtin.os == builtin.Os.linux) {
|
||||
const auxv = @ptrCast([*]usize, envp.ptr + envp_count + 1);
|
||||
var i: usize = 0;
|
||||
|
||||
@ -19,7 +19,7 @@ export fn memset(dest: ?[*]u8, c: u8, n: usize) ?[*]u8 {
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1)
|
||||
(??dest)[index] = c;
|
||||
dest.?[index] = c;
|
||||
|
||||
return dest;
|
||||
}
|
||||
@ -29,7 +29,7 @@ export fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) ?[*]
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1)
|
||||
(??dest)[index] = (??src)[index];
|
||||
dest.?[index] = src.?[index];
|
||||
|
||||
return dest;
|
||||
}
|
||||
@ -40,13 +40,13 @@ export fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) ?[*]u8 {
|
||||
if (@ptrToInt(dest) < @ptrToInt(src)) {
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1) {
|
||||
(??dest)[index] = (??src)[index];
|
||||
dest.?[index] = src.?[index];
|
||||
}
|
||||
} else {
|
||||
var index = n;
|
||||
while (index != 0) {
|
||||
index -= 1;
|
||||
(??dest)[index] = (??src)[index];
|
||||
dest.?[index] = src.?[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -286,15 +286,15 @@ fn testUtf8IteratorOnAscii() void {
|
||||
const s = Utf8View.initComptime("abc");
|
||||
|
||||
var it1 = s.iterator();
|
||||
debug.assert(std.mem.eql(u8, "a", ??it1.nextCodepointSlice()));
|
||||
debug.assert(std.mem.eql(u8, "b", ??it1.nextCodepointSlice()));
|
||||
debug.assert(std.mem.eql(u8, "c", ??it1.nextCodepointSlice()));
|
||||
debug.assert(std.mem.eql(u8, "a", it1.nextCodepointSlice().?));
|
||||
debug.assert(std.mem.eql(u8, "b", it1.nextCodepointSlice().?));
|
||||
debug.assert(std.mem.eql(u8, "c", it1.nextCodepointSlice().?));
|
||||
debug.assert(it1.nextCodepointSlice() == null);
|
||||
|
||||
var it2 = s.iterator();
|
||||
debug.assert(??it2.nextCodepoint() == 'a');
|
||||
debug.assert(??it2.nextCodepoint() == 'b');
|
||||
debug.assert(??it2.nextCodepoint() == 'c');
|
||||
debug.assert(it2.nextCodepoint().? == 'a');
|
||||
debug.assert(it2.nextCodepoint().? == 'b');
|
||||
debug.assert(it2.nextCodepoint().? == 'c');
|
||||
debug.assert(it2.nextCodepoint() == null);
|
||||
}
|
||||
|
||||
@ -321,15 +321,15 @@ fn testUtf8ViewOk() void {
|
||||
const s = Utf8View.initComptime("東京市");
|
||||
|
||||
var it1 = s.iterator();
|
||||
debug.assert(std.mem.eql(u8, "東", ??it1.nextCodepointSlice()));
|
||||
debug.assert(std.mem.eql(u8, "京", ??it1.nextCodepointSlice()));
|
||||
debug.assert(std.mem.eql(u8, "市", ??it1.nextCodepointSlice()));
|
||||
debug.assert(std.mem.eql(u8, "東", it1.nextCodepointSlice().?));
|
||||
debug.assert(std.mem.eql(u8, "京", it1.nextCodepointSlice().?));
|
||||
debug.assert(std.mem.eql(u8, "市", it1.nextCodepointSlice().?));
|
||||
debug.assert(it1.nextCodepointSlice() == null);
|
||||
|
||||
var it2 = s.iterator();
|
||||
debug.assert(??it2.nextCodepoint() == 0x6771);
|
||||
debug.assert(??it2.nextCodepoint() == 0x4eac);
|
||||
debug.assert(??it2.nextCodepoint() == 0x5e02);
|
||||
debug.assert(it2.nextCodepoint().? == 0x6771);
|
||||
debug.assert(it2.nextCodepoint().? == 0x4eac);
|
||||
debug.assert(it2.nextCodepoint().? == 0x5e02);
|
||||
debug.assert(it2.nextCodepoint() == null);
|
||||
}
|
||||
|
||||
|
||||
@ -1417,7 +1417,7 @@ pub const Node = struct {
|
||||
Range,
|
||||
Sub,
|
||||
SubWrap,
|
||||
UnwrapMaybe,
|
||||
UnwrapOptional,
|
||||
};
|
||||
|
||||
pub fn iterate(self: *InfixOp, index: usize) ?*Node {
|
||||
@ -1475,7 +1475,7 @@ pub const Node = struct {
|
||||
Op.Range,
|
||||
Op.Sub,
|
||||
Op.SubWrap,
|
||||
Op.UnwrapMaybe,
|
||||
Op.UnwrapOptional,
|
||||
=> {},
|
||||
}
|
||||
|
||||
@ -1507,14 +1507,13 @@ pub const Node = struct {
|
||||
BitNot,
|
||||
BoolNot,
|
||||
Cancel,
|
||||
MaybeType,
|
||||
OptionalType,
|
||||
Negation,
|
||||
NegationWrap,
|
||||
Resume,
|
||||
PtrType: PtrInfo,
|
||||
SliceType: PtrInfo,
|
||||
Try,
|
||||
UnwrapMaybe,
|
||||
};
|
||||
|
||||
pub const PtrInfo = struct {
|
||||
@ -1557,12 +1556,12 @@ pub const Node = struct {
|
||||
Op.BitNot,
|
||||
Op.BoolNot,
|
||||
Op.Cancel,
|
||||
Op.MaybeType,
|
||||
Op.OptionalType,
|
||||
Op.Negation,
|
||||
Op.NegationWrap,
|
||||
Op.Try,
|
||||
Op.Resume,
|
||||
Op.UnwrapMaybe,
|
||||
Op.UnwrapOptional,
|
||||
Op.PointerType,
|
||||
=> {},
|
||||
}
|
||||
@ -1619,6 +1618,7 @@ pub const Node = struct {
|
||||
ArrayInitializer: InitList,
|
||||
StructInitializer: InitList,
|
||||
Deref,
|
||||
UnwrapOptional,
|
||||
|
||||
pub const InitList = SegmentedList(*Node, 2);
|
||||
|
||||
|
||||
@ -711,7 +711,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
|
||||
else => {
|
||||
// TODO: this is a special case. Remove this when #760 is fixed
|
||||
if (token_ptr.id == Token.Id.Keyword_error) {
|
||||
if ((??tok_it.peek()).id == Token.Id.LBrace) {
|
||||
if (tok_it.peek().?.id == Token.Id.LBrace) {
|
||||
const error_type_node = try arena.construct(ast.Node.ErrorType{
|
||||
.base = ast.Node{ .id = ast.Node.Id.ErrorType },
|
||||
.token = token_index,
|
||||
@ -1434,8 +1434,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
|
||||
try stack.append(State{
|
||||
.ExpectTokenSave = ExpectTokenSave{
|
||||
.id = Token.Id.AngleBracketRight,
|
||||
.ptr = &??async_node.rangle_bracket,
|
||||
},
|
||||
.ptr = &async_node.rangle_bracket.? },
|
||||
});
|
||||
try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &async_node.allocator_type } });
|
||||
continue;
|
||||
@ -1567,7 +1566,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
|
||||
.bit_range = null,
|
||||
};
|
||||
// TODO https://github.com/ziglang/zig/issues/1022
|
||||
const align_info = &??addr_of_info.align_info;
|
||||
const align_info = &addr_of_info.align_info.?;
|
||||
|
||||
try stack.append(State{ .AlignBitRange = align_info });
|
||||
try stack.append(State{ .Expression = OptionalCtx{ .Required = &align_info.node } });
|
||||
@ -1604,7 +1603,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
|
||||
switch (token.ptr.id) {
|
||||
Token.Id.Colon => {
|
||||
align_info.bit_range = ast.Node.PrefixOp.PtrInfo.Align.BitRange(undefined);
|
||||
const bit_range = &??align_info.bit_range;
|
||||
const bit_range = &align_info.bit_range.?;
|
||||
|
||||
try stack.append(State{ .ExpectToken = Token.Id.RParen });
|
||||
try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.end } });
|
||||
@ -2144,7 +2143,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
|
||||
State.CurlySuffixExpressionEnd => |opt_ctx| {
|
||||
const lhs = opt_ctx.get() ?? continue;
|
||||
|
||||
if ((??tok_it.peek()).id == Token.Id.Period) {
|
||||
if (tok_it.peek().?.id == Token.Id.Period) {
|
||||
const node = try arena.construct(ast.Node.SuffixOp{
|
||||
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
|
||||
.lhs = lhs,
|
||||
@ -2326,6 +2325,17 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
|
||||
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
|
||||
continue;
|
||||
}
|
||||
if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {
|
||||
const node = try arena.construct(ast.Node.SuffixOp{
|
||||
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
|
||||
.lhs = lhs,
|
||||
.op = ast.Node.SuffixOp.Op.UnwrapOptional,
|
||||
.rtoken = question_token,
|
||||
});
|
||||
opt_ctx.store(&node.base);
|
||||
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
|
||||
continue;
|
||||
}
|
||||
const node = try arena.construct(ast.Node.InfixOp{
|
||||
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
|
||||
.lhs = lhs,
|
||||
@ -2403,7 +2413,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
|
||||
.arrow_token = next_token_index,
|
||||
.return_type = undefined,
|
||||
};
|
||||
const return_type_ptr = &((??node.result).return_type);
|
||||
const return_type_ptr = &node.result.?.return_type;
|
||||
try stack.append(State{ .Expression = OptionalCtx{ .Required = return_type_ptr } });
|
||||
continue;
|
||||
},
|
||||
@ -2875,7 +2885,7 @@ const OptionalCtx = union(enum) {
|
||||
pub fn get(self: *const OptionalCtx) ?*ast.Node {
|
||||
switch (self.*) {
|
||||
OptionalCtx.Optional => |ptr| return ptr.*,
|
||||
OptionalCtx.RequiredNull => |ptr| return ??ptr.*,
|
||||
OptionalCtx.RequiredNull => |ptr| return ptr.*.?,
|
||||
OptionalCtx.Required => |ptr| return ptr.*,
|
||||
}
|
||||
}
|
||||
@ -3237,7 +3247,7 @@ fn tokenIdToAssignment(id: *const Token.Id) ?ast.Node.InfixOp.Op {
|
||||
fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
|
||||
return switch (id) {
|
||||
Token.Id.Keyword_catch => ast.Node.InfixOp.Op{ .Catch = null },
|
||||
Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op{ .UnwrapMaybe = void{} },
|
||||
Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op{ .UnwrapOptional = void{} },
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
@ -3299,8 +3309,7 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
|
||||
.volatile_token = null,
|
||||
},
|
||||
},
|
||||
Token.Id.QuestionMark => ast.Node.PrefixOp.Op{ .MaybeType = void{} },
|
||||
Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op{ .UnwrapMaybe = void{} },
|
||||
Token.Id.QuestionMark => ast.Node.PrefixOp.Op{ .OptionalType = void{} },
|
||||
Token.Id.Keyword_await => ast.Node.PrefixOp.Op{ .Await = void{} },
|
||||
Token.Id.Keyword_try => ast.Node.PrefixOp.Op{ .Try = void{} },
|
||||
else => null,
|
||||
@ -3322,7 +3331,7 @@ fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: *const OptionalCtx, compti
|
||||
}
|
||||
|
||||
fn eatToken(tok_it: *ast.Tree.TokenList.Iterator, tree: *ast.Tree, id: @TagType(Token.Id)) ?TokenIndex {
|
||||
const token = ??tok_it.peek();
|
||||
const token = tok_it.peek().?;
|
||||
|
||||
if (token.id == id) {
|
||||
return nextToken(tok_it, tree).index;
|
||||
@ -3334,7 +3343,7 @@ fn eatToken(tok_it: *ast.Tree.TokenList.Iterator, tree: *ast.Tree, id: @TagType(
|
||||
fn nextToken(tok_it: *ast.Tree.TokenList.Iterator, tree: *ast.Tree) AnnotatedToken {
|
||||
const result = AnnotatedToken{
|
||||
.index = tok_it.index,
|
||||
.ptr = ??tok_it.next(),
|
||||
.ptr = tok_it.next().?,
|
||||
};
|
||||
assert(result.ptr.id != Token.Id.LineComment);
|
||||
|
||||
|
||||
@ -650,9 +650,10 @@ test "zig fmt: statements with empty line between" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: ptr deref operator" {
|
||||
test "zig fmt: ptr deref operator and unwrap optional operator" {
|
||||
try testCanonical(
|
||||
\\const a = b.*;
|
||||
\\const a = b.?;
|
||||
\\
|
||||
);
|
||||
}
|
||||
@ -1209,7 +1210,7 @@ test "zig fmt: precedence" {
|
||||
test "zig fmt: prefix operators" {
|
||||
try testCanonical(
|
||||
\\test "prefix operators" {
|
||||
\\ try return --%~??!*&0;
|
||||
\\ try return --%~!*&0;
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
|
||||
@ -222,7 +222,7 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
|
||||
}
|
||||
}
|
||||
|
||||
const value_expr = ??tag.value_expr;
|
||||
const value_expr = tag.value_expr.?;
|
||||
try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, start_col, Space.Space); // =
|
||||
try renderExpression(allocator, stream, tree, indent, start_col, value_expr, Space.Comma); // value,
|
||||
},
|
||||
@ -465,8 +465,7 @@ fn renderExpression(
|
||||
ast.Node.PrefixOp.Op.BoolNot,
|
||||
ast.Node.PrefixOp.Op.Negation,
|
||||
ast.Node.PrefixOp.Op.NegationWrap,
|
||||
ast.Node.PrefixOp.Op.UnwrapMaybe,
|
||||
ast.Node.PrefixOp.Op.MaybeType,
|
||||
ast.Node.PrefixOp.Op.OptionalType,
|
||||
ast.Node.PrefixOp.Op.AddressOf,
|
||||
=> {
|
||||
try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None);
|
||||
@ -513,7 +512,7 @@ fn renderExpression(
|
||||
|
||||
var it = call_info.params.iterator(0);
|
||||
while (true) {
|
||||
const param_node = ??it.next();
|
||||
const param_node = it.next().?;
|
||||
|
||||
const param_node_new_indent = if (param_node.*.id == ast.Node.Id.MultilineStringLiteral) blk: {
|
||||
break :blk indent;
|
||||
@ -559,10 +558,10 @@ fn renderExpression(
|
||||
return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
|
||||
},
|
||||
|
||||
ast.Node.SuffixOp.Op.Deref => {
|
||||
ast.Node.SuffixOp.Op.Deref, ast.Node.SuffixOp.Op.UnwrapOptional => {
|
||||
try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
|
||||
try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
|
||||
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // *
|
||||
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // * or ?
|
||||
},
|
||||
|
||||
@TagType(ast.Node.SuffixOp.Op).Slice => |range| {
|
||||
@ -595,7 +594,7 @@ fn renderExpression(
|
||||
}
|
||||
|
||||
if (field_inits.len == 1) blk: {
|
||||
const field_init = ??field_inits.at(0).*.cast(ast.Node.FieldInitializer);
|
||||
const field_init = field_inits.at(0).*.cast(ast.Node.FieldInitializer).?;
|
||||
|
||||
if (field_init.expr.cast(ast.Node.SuffixOp)) |nested_suffix_op| {
|
||||
if (nested_suffix_op.op == ast.Node.SuffixOp.Op.StructInitializer) {
|
||||
@ -688,7 +687,7 @@ fn renderExpression(
|
||||
var count: usize = 1;
|
||||
var it = exprs.iterator(0);
|
||||
while (true) {
|
||||
const expr = (??it.next()).*;
|
||||
const expr = it.next().?.*;
|
||||
if (it.peek()) |next_expr| {
|
||||
const expr_last_token = expr.*.lastToken() + 1;
|
||||
const loc = tree.tokenLocation(tree.tokens.at(expr_last_token).end, next_expr.*.firstToken());
|
||||
@ -806,7 +805,7 @@ fn renderExpression(
|
||||
},
|
||||
}
|
||||
|
||||
return renderExpression(allocator, stream, tree, indent, start_col, ??flow_expr.rhs, space);
|
||||
return renderExpression(allocator, stream, tree, indent, start_col, flow_expr.rhs.?, space);
|
||||
},
|
||||
|
||||
ast.Node.Id.Payload => {
|
||||
@ -1245,7 +1244,7 @@ fn renderExpression(
|
||||
} else {
|
||||
var it = switch_case.items.iterator(0);
|
||||
while (true) {
|
||||
const node = ??it.next();
|
||||
const node = it.next().?;
|
||||
if (it.peek()) |next_node| {
|
||||
try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
|
||||
|
||||
@ -1550,7 +1549,7 @@ fn renderExpression(
|
||||
|
||||
var it = asm_node.outputs.iterator(0);
|
||||
while (true) {
|
||||
const asm_output = ??it.next();
|
||||
const asm_output = it.next().?;
|
||||
const node = &(asm_output.*).base;
|
||||
|
||||
if (it.peek()) |next_asm_output| {
|
||||
@ -1588,7 +1587,7 @@ fn renderExpression(
|
||||
|
||||
var it = asm_node.inputs.iterator(0);
|
||||
while (true) {
|
||||
const asm_input = ??it.next();
|
||||
const asm_input = it.next().?;
|
||||
const node = &(asm_input.*).base;
|
||||
|
||||
if (it.peek()) |next_asm_input| {
|
||||
@ -1620,7 +1619,7 @@ fn renderExpression(
|
||||
|
||||
var it = asm_node.clobbers.iterator(0);
|
||||
while (true) {
|
||||
const clobber_token = ??it.next();
|
||||
const clobber_token = it.next().?;
|
||||
|
||||
if (it.peek() == null) {
|
||||
try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.Newline);
|
||||
|
||||
@ -9,7 +9,7 @@ const Value = struct {
|
||||
align_expr: ?u32,
|
||||
};
|
||||
|
||||
test "nullable if after an if in a switch prong of a switch with 2 prongs in an else" {
|
||||
test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
|
||||
foo(false, true);
|
||||
}
|
||||
|
||||
|
||||
@ -109,16 +109,16 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
|
||||
const Self = this;
|
||||
x: u8,
|
||||
fn constConst(p: *const *const Self) u8 {
|
||||
return (p.*).x;
|
||||
return p.*.x;
|
||||
}
|
||||
fn maybeConstConst(p: ?*const *const Self) u8 {
|
||||
return ((??p).*).x;
|
||||
return p.?.*.x;
|
||||
}
|
||||
fn constConstConst(p: *const *const *const Self) u8 {
|
||||
return (p.*.*).x;
|
||||
return p.*.*.x;
|
||||
}
|
||||
fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
|
||||
return ((??p).*.*).x;
|
||||
return p.?.*.*.x;
|
||||
}
|
||||
};
|
||||
const s = S{ .x = 42 };
|
||||
@ -177,56 +177,56 @@ test "string literal to &const []const u8" {
|
||||
}
|
||||
|
||||
test "implicitly cast from T to error!?T" {
|
||||
castToMaybeTypeError(1);
|
||||
comptime castToMaybeTypeError(1);
|
||||
castToOptionalTypeError(1);
|
||||
comptime castToOptionalTypeError(1);
|
||||
}
|
||||
const A = struct {
|
||||
a: i32,
|
||||
};
|
||||
fn castToMaybeTypeError(z: i32) void {
|
||||
fn castToOptionalTypeError(z: i32) void {
|
||||
const x = i32(1);
|
||||
const y: error!?i32 = x;
|
||||
assert(??(try y) == 1);
|
||||
assert((try y).? == 1);
|
||||
|
||||
const f = z;
|
||||
const g: error!?i32 = f;
|
||||
|
||||
const a = A{ .a = z };
|
||||
const b: error!?A = a;
|
||||
assert((??(b catch unreachable)).a == 1);
|
||||
assert((b catch unreachable).?.a == 1);
|
||||
}
|
||||
|
||||
test "implicitly cast from int to error!?T" {
|
||||
implicitIntLitToMaybe();
|
||||
comptime implicitIntLitToMaybe();
|
||||
implicitIntLitToOptional();
|
||||
comptime implicitIntLitToOptional();
|
||||
}
|
||||
fn implicitIntLitToMaybe() void {
|
||||
fn implicitIntLitToOptional() void {
|
||||
const f: ?i32 = 1;
|
||||
const g: error!?i32 = 1;
|
||||
}
|
||||
|
||||
test "return null from fn() error!?&T" {
|
||||
const a = returnNullFromMaybeTypeErrorRef();
|
||||
const b = returnNullLitFromMaybeTypeErrorRef();
|
||||
const a = returnNullFromOptionalTypeErrorRef();
|
||||
const b = returnNullLitFromOptionalTypeErrorRef();
|
||||
assert((try a) == null and (try b) == null);
|
||||
}
|
||||
fn returnNullFromMaybeTypeErrorRef() error!?*A {
|
||||
fn returnNullFromOptionalTypeErrorRef() error!?*A {
|
||||
const a: ?*A = null;
|
||||
return a;
|
||||
}
|
||||
fn returnNullLitFromMaybeTypeErrorRef() error!?*A {
|
||||
fn returnNullLitFromOptionalTypeErrorRef() error!?*A {
|
||||
return null;
|
||||
}
|
||||
|
||||
test "peer type resolution: ?T and T" {
|
||||
assert(??peerTypeTAndMaybeT(true, false) == 0);
|
||||
assert(??peerTypeTAndMaybeT(false, false) == 3);
|
||||
assert(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
assert(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
comptime {
|
||||
assert(??peerTypeTAndMaybeT(true, false) == 0);
|
||||
assert(??peerTypeTAndMaybeT(false, false) == 3);
|
||||
assert(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
assert(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
}
|
||||
}
|
||||
fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize {
|
||||
fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
|
||||
if (c) {
|
||||
return if (b) null else usize(0);
|
||||
}
|
||||
@ -251,11 +251,11 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
|
||||
}
|
||||
|
||||
test "implicitly cast from [N]T to ?[]const T" {
|
||||
assert(mem.eql(u8, ??castToMaybeSlice(), "hi"));
|
||||
comptime assert(mem.eql(u8, ??castToMaybeSlice(), "hi"));
|
||||
assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||
comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||
}
|
||||
|
||||
fn castToMaybeSlice() ?[]const u8 {
|
||||
fn castToOptionalSlice() ?[]const u8 {
|
||||
return "hi";
|
||||
}
|
||||
|
||||
@ -404,5 +404,5 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
|
||||
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
|
||||
const window_name = [1][*]const u8{c"window name"};
|
||||
const x: [*]const ?[*]const u8 = &window_name;
|
||||
assert(mem.eql(u8, std.cstr.toSliceConst(??x[0]), "window name"));
|
||||
assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
|
||||
if (x) |v| assert(v == 1234) else |err| @compileError("bad");
|
||||
}
|
||||
|
||||
test "syntax: nullable operator in front of error union operator" {
|
||||
test "syntax: optional operator in front of error union operator" {
|
||||
comptime {
|
||||
assert(?error!i32 == ?(error!i32));
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ fn fibonacci(x: i32) i32 {
|
||||
}
|
||||
|
||||
fn unwrapAndAddOne(blah: ?i32) i32 {
|
||||
return ??blah + 1;
|
||||
return blah.? + 1;
|
||||
}
|
||||
const should_be_1235 = unwrapAndAddOne(1234);
|
||||
test "static add one" {
|
||||
|
||||
@ -127,7 +127,7 @@ test "generic fn with implicit cast" {
|
||||
}) == 0);
|
||||
}
|
||||
fn getByte(ptr: ?*const u8) u8 {
|
||||
return (??ptr).*;
|
||||
return ptr.?.*;
|
||||
}
|
||||
fn getFirstByte(comptime T: type, mem: []const T) u8 {
|
||||
return getByte(@ptrCast(*const u8, &mem[0]));
|
||||
|
||||
@ -505,7 +505,7 @@ test "@typeId" {
|
||||
assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
|
||||
assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
|
||||
assert(@typeId(@typeOf(null)) == Tid.Null);
|
||||
assert(@typeId(?i32) == Tid.Nullable);
|
||||
assert(@typeId(?i32) == Tid.Optional);
|
||||
assert(@typeId(error!i32) == Tid.ErrorUnion);
|
||||
assert(@typeId(error) == Tid.ErrorSet);
|
||||
assert(@typeId(AnEnum) == Tid.Enum);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "nullable type" {
|
||||
test "optional type" {
|
||||
const x: ?bool = true;
|
||||
|
||||
if (x) |y| {
|
||||
@ -33,7 +33,7 @@ test "test maybe object and get a pointer to the inner value" {
|
||||
b.* = false;
|
||||
}
|
||||
|
||||
assert(??maybe_bool == false);
|
||||
assert(maybe_bool.? == false);
|
||||
}
|
||||
|
||||
test "rhs maybe unwrap return" {
|
||||
@ -47,9 +47,9 @@ test "maybe return" {
|
||||
}
|
||||
|
||||
fn maybeReturnImpl() void {
|
||||
assert(??foo(1235));
|
||||
assert(foo(1235).?);
|
||||
if (foo(null) != null) unreachable;
|
||||
assert(!??foo(1234));
|
||||
assert(!foo(1234).?);
|
||||
}
|
||||
|
||||
fn foo(x: ?i32) ?bool {
|
||||
@ -102,12 +102,12 @@ fn testTestNullRuntime(x: ?i32) void {
|
||||
assert(!(x != null));
|
||||
}
|
||||
|
||||
test "nullable void" {
|
||||
nullableVoidImpl();
|
||||
comptime nullableVoidImpl();
|
||||
test "optional void" {
|
||||
optionalVoidImpl();
|
||||
comptime optionalVoidImpl();
|
||||
}
|
||||
|
||||
fn nullableVoidImpl() void {
|
||||
fn optionalVoidImpl() void {
|
||||
assert(bar(null) == null);
|
||||
assert(bar({}) != null);
|
||||
}
|
||||
@ -120,19 +120,19 @@ fn bar(x: ?void) ?void {
|
||||
}
|
||||
}
|
||||
|
||||
const StructWithNullable = struct {
|
||||
const StructWithOptional = struct {
|
||||
field: ?i32,
|
||||
};
|
||||
|
||||
var struct_with_nullable: StructWithNullable = undefined;
|
||||
var struct_with_optional: StructWithOptional = undefined;
|
||||
|
||||
test "unwrap nullable which is field of global var" {
|
||||
struct_with_nullable.field = null;
|
||||
if (struct_with_nullable.field) |payload| {
|
||||
test "unwrap optional which is field of global var" {
|
||||
struct_with_optional.field = null;
|
||||
if (struct_with_optional.field) |payload| {
|
||||
unreachable;
|
||||
}
|
||||
struct_with_nullable.field = 1234;
|
||||
if (struct_with_nullable.field) |payload| {
|
||||
struct_with_optional.field = 1234;
|
||||
if (struct_with_optional.field) |payload| {
|
||||
assert(payload == 1234);
|
||||
} else {
|
||||
unreachable;
|
||||
|
||||
@ -2,7 +2,7 @@ const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
const reflection = this;
|
||||
|
||||
test "reflection: array, pointer, nullable, error union type child" {
|
||||
test "reflection: array, pointer, optional, error union type child" {
|
||||
comptime {
|
||||
assert(([10]u8).Child == u8);
|
||||
assert((*u8).Child == u8);
|
||||
|
||||
@ -88,15 +88,15 @@ fn testArray() void {
|
||||
assert(arr_info.Array.child == bool);
|
||||
}
|
||||
|
||||
test "type info: nullable type info" {
|
||||
testNullable();
|
||||
comptime testNullable();
|
||||
test "type info: optional type info" {
|
||||
testOptional();
|
||||
comptime testOptional();
|
||||
}
|
||||
|
||||
fn testNullable() void {
|
||||
fn testOptional() void {
|
||||
const null_info = @typeInfo(?void);
|
||||
assert(TypeId(null_info) == TypeId.Nullable);
|
||||
assert(null_info.Nullable.child == void);
|
||||
assert(TypeId(null_info) == TypeId.Optional);
|
||||
assert(null_info.Optional.child == void);
|
||||
}
|
||||
|
||||
test "type info: promise info" {
|
||||
@ -168,7 +168,7 @@ fn testUnion() void {
|
||||
assert(typeinfo_info.Union.tag_type == TypeId);
|
||||
assert(typeinfo_info.Union.fields.len == 25);
|
||||
assert(typeinfo_info.Union.fields[4].enum_field != null);
|
||||
assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
|
||||
assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
|
||||
assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
|
||||
assert(typeinfo_info.Union.defs.len == 20);
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ test "while with else" {
|
||||
assert(got_else == 1);
|
||||
}
|
||||
|
||||
test "while with nullable as condition" {
|
||||
test "while with optional as condition" {
|
||||
numbers_left = 10;
|
||||
var sum: i32 = 0;
|
||||
while (getNumberOrNull()) |value| {
|
||||
@ -90,7 +90,7 @@ test "while with nullable as condition" {
|
||||
assert(sum == 45);
|
||||
}
|
||||
|
||||
test "while with nullable as condition with else" {
|
||||
test "while with optional as condition with else" {
|
||||
numbers_left = 10;
|
||||
var sum: i32 = 0;
|
||||
var got_else: i32 = 0;
|
||||
@ -132,7 +132,7 @@ fn getNumberOrNull() ?i32 {
|
||||
};
|
||||
}
|
||||
|
||||
test "while on nullable with else result follow else prong" {
|
||||
test "while on optional with else result follow else prong" {
|
||||
const result = while (returnNull()) |value| {
|
||||
break value;
|
||||
} else
|
||||
@ -140,8 +140,8 @@ test "while on nullable with else result follow else prong" {
|
||||
assert(result == 2);
|
||||
}
|
||||
|
||||
test "while on nullable with else result follow break prong" {
|
||||
const result = while (returnMaybe(10)) |value| {
|
||||
test "while on optional with else result follow break prong" {
|
||||
const result = while (returnOptional(10)) |value| {
|
||||
break value;
|
||||
} else
|
||||
i32(2);
|
||||
@ -210,7 +210,7 @@ fn testContinueOuter() void {
|
||||
fn returnNull() ?i32 {
|
||||
return null;
|
||||
}
|
||||
fn returnMaybe(x: i32) ?i32 {
|
||||
fn returnOptional(x: i32) ?i32 {
|
||||
return x;
|
||||
}
|
||||
fn returnError() error!i32 {
|
||||
|
||||
@ -1341,7 +1341,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ if (true) |x| { }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:9: error: expected nullable type, found 'bool'",
|
||||
".tmp_source.zig:2:9: error: expected optional type, found 'bool'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -1780,7 +1780,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"assign null to non-nullable pointer",
|
||||
"assign null to non-optional pointer",
|
||||
\\const a: *u8 = null;
|
||||
\\
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(a)); }
|
||||
@ -2817,7 +2817,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"while expected bool, got nullable",
|
||||
"while expected bool, got optional",
|
||||
\\export fn foo() void {
|
||||
\\ while (bar()) {}
|
||||
\\}
|
||||
@ -2837,23 +2837,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"while expected nullable, got bool",
|
||||
"while expected optional, got bool",
|
||||
\\export fn foo() void {
|
||||
\\ while (bar()) |x| {}
|
||||
\\}
|
||||
\\fn bar() bool { return true; }
|
||||
,
|
||||
".tmp_source.zig:2:15: error: expected nullable type, found 'bool'",
|
||||
".tmp_source.zig:2:15: error: expected optional type, found 'bool'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"while expected nullable, got error union",
|
||||
"while expected optional, got error union",
|
||||
\\export fn foo() void {
|
||||
\\ while (bar()) |x| {}
|
||||
\\}
|
||||
\\fn bar() error!i32 { return 1; }
|
||||
,
|
||||
".tmp_source.zig:2:15: error: expected nullable type, found 'error!i32'",
|
||||
".tmp_source.zig:2:15: error: expected optional type, found 'error!i32'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2867,7 +2867,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"while expected error union, got nullable",
|
||||
"while expected error union, got optional",
|
||||
\\export fn foo() void {
|
||||
\\ while (bar()) |x| {} else |err| {}
|
||||
\\}
|
||||
|
||||
@ -282,8 +282,8 @@ pub const CompareOutputContext = struct {
|
||||
var stdout = Buffer.initNull(b.allocator);
|
||||
var stderr = Buffer.initNull(b.allocator);
|
||||
|
||||
var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
|
||||
var stdout_file_in_stream = io.FileInStream.init(&child.stdout.?);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&child.stderr.?);
|
||||
|
||||
stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable;
|
||||
stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable;
|
||||
@ -601,8 +601,8 @@ pub const CompileErrorContext = struct {
|
||||
var stdout_buf = Buffer.initNull(b.allocator);
|
||||
var stderr_buf = Buffer.initNull(b.allocator);
|
||||
|
||||
var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
|
||||
var stdout_file_in_stream = io.FileInStream.init(&child.stdout.?);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&child.stderr.?);
|
||||
|
||||
stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
|
||||
stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
|
||||
@ -872,8 +872,8 @@ pub const TranslateCContext = struct {
|
||||
var stdout_buf = Buffer.initNull(b.allocator);
|
||||
var stderr_buf = Buffer.initNull(b.allocator);
|
||||
|
||||
var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
|
||||
var stdout_file_in_stream = io.FileInStream.init(&child.stdout.?);
|
||||
var stderr_file_in_stream = io.FileInStream.init(&child.stderr.?);
|
||||
|
||||
stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
|
||||
stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user