breaking syntax change: ??x to x.? (#1095)

See #1023

This also renames Nullable/Maybe to Optional
This commit is contained in:
Andrew Kelley 2018-06-09 23:42:14 -04:00 committed by GitHub
parent d464b25322
commit ec1b6f6673
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 489 additions and 482 deletions

View File

@ -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

View File

@ -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.

View File

@ -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 &amp;x ?x ??x
x{} x.*
!x -x -%x ~x &amp;x ?x
x{} x.* x.?
! * / % ** *%
+ - ++ +% -%
&lt;&lt; &gt;&gt;
@ -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("&lt;" SuffixOpExpression "&gt;") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression)
SuffixOpExpression = ("async" option("&lt;" SuffixOpExpression "&gt;") 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

View File

@ -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();

View File

@ -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"));

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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:

View File

@ -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();

View File

@ -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();

View File

@ -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:

View File

@ -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);

View File

@ -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("&lt;" SuffixOpExpression "&gt;") 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;

View File

@ -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 "-%=";

View File

@ -100,8 +100,7 @@ enum TokenId {
TokenIdLBrace,
TokenIdLBracket,
TokenIdLParen,
TokenIdMaybe,
TokenIdMaybeAssign,
TokenIdQuestion,
TokenIdMinusEq,
TokenIdMinusPercent,
TokenIdMinusPercentEq,

View File

@ -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;

View File

@ -258,7 +258,7 @@ test "iterator ArrayList test" {
}
it.reset();
assert(??it.next() == 1);
assert(it.next().? == 1);
}
test "insert ArrayList test" {

View File

@ -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");

View File

@ -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);
}

View File

@ -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;

View File

@ -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]);
}

View File

@ -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"),
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 };

View File

@ -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);
}

View File

@ -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.?);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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{});

View File

@ -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;

View File

@ -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];
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
\\}
\\
);

View File

@ -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);

View File

@ -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);
}

View File

@ -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"));
}

View File

@ -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));
}

View File

@ -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" {

View File

@ -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]));

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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| {}
\\}

View File

@ -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;