From 1696e943acd67119104f303467c0e26eecb94544 Mon Sep 17 00:00:00 2001
From: Tadeo Kondrak
Date: Tue, 28 Apr 2020 11:14:47 -0600
Subject: Implement @typeInfo for @Frame()
Closes https://github.com/ziglang/zig/issues/3066
---
src/analyze.cpp | 13 +++++++++++++
1 file changed, 13 insertions(+)
(limited to 'src/analyze.cpp')
diff --git a/src/analyze.cpp b/src/analyze.cpp
index d170273808..5eb0205dfb 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -6021,6 +6021,19 @@ ZigValue *create_const_null(CodeGen *g, ZigType *type) {
return const_val;
}
+void init_const_fn(ZigValue *const_val, ZigFn *fn) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->type = fn->type_entry;
+ const_val->data.x_ptr.special = ConstPtrSpecialFunction;
+ const_val->data.x_ptr.data.fn.fn_entry = fn;
+}
+
+ZigValue *create_const_fn(CodeGen *g, ZigFn *fn) {
+ ZigValue *const_val = g->pass1_arena->create();
+ init_const_fn(const_val, fn);
+ return const_val;
+}
+
void init_const_float(ZigValue *const_val, ZigType *type, double value) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
--
cgit v1.2.3
From 129a4fb251f8eab22eacf219fbf81006baec3251 Mon Sep 17 00:00:00 2001
From: Alexandros Naskos
Date: Wed, 24 Jun 2020 20:00:11 +0300
Subject: Copy union const values correctly
---
src/analyze.cpp | 6 ++++++
test/stage1/behavior/type_info.zig | 8 ++++++++
2 files changed, 14 insertions(+)
(limited to 'src/analyze.cpp')
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 542fbb56ce..699b121276 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -9597,6 +9597,12 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
break;
}
}
+ } else if (dest->type->id == ZigTypeIdUnion) {
+ bigint_init_bigint(&dest->data.x_union.tag, &src->data.x_union.tag);
+ dest->data.x_union.payload = g->pass1_arena->create();
+ copy_const_val(g, dest->data.x_union.payload, src->data.x_union.payload);
+ dest->data.x_union.payload->parent.id = ConstParentIdUnion;
+ dest->data.x_union.payload->parent.data.p_union.union_val = dest;
} else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
dest->data.x_optional = g->pass1_arena->create();
copy_const_val(g, dest->data.x_optional, src->data.x_optional);
diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig
index 41301f290d..68ff3aa310 100644
--- a/test/stage1/behavior/type_info.zig
+++ b/test/stage1/behavior/type_info.zig
@@ -402,3 +402,11 @@ test "type info for async frames" {
else => unreachable,
}
}
+
+test "type info: value is correctly copied" {
+ comptime {
+ var ptrInfo = @typeInfo([]u32);
+ ptrInfo.Pointer.size = .One;
+ expect(@typeInfo([]u32).Pointer.size == .Slice);
+ }
+}
--
cgit v1.2.3
From 5667a21b1e7b8aa2dfcefed81d2b594029a116db Mon Sep 17 00:00:00 2001
From: Vexu
Date: Tue, 7 Jul 2020 23:31:38 +0300
Subject: fix missing check on extern variables with no type
---
src/analyze.cpp | 4 ++++
test/compile_errors.zig | 9 +++++++++
2 files changed, 13 insertions(+)
(limited to 'src/analyze.cpp')
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 699b121276..afe0fe6849 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -4012,6 +4012,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
} else if (!is_extern) {
add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
implicit_type = g->builtin_types.entry_invalid;
+ } else if (explicit_type == nullptr) {
+ // extern variable without explicit type
+ add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
+ implicit_type = g->builtin_types.entry_invalid;
}
ZigType *type = explicit_type ? explicit_type : implicit_type;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index adf92800fe..611094c050 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,15 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add("extern variable has no type",
+ \\extern var foo;
+ \\pub export fn entry() void {
+ \\ foo;
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:1:1: error: unable to infer variable type",
+ });
+
cases.add("@src outside function",
\\comptime {
\\ @src();
--
cgit v1.2.3
From 8110639c7964fcb23c2b715f97ab6caa27506b93 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Sat, 11 Jul 2020 14:08:20 +0300
Subject: add 'anytype' to stage1 and langref
---
doc/langref.html.in | 87 +++++++++++++++++++++++++++--------------------------
src/all_types.hpp | 8 ++---
src/analyze.cpp | 16 +++++-----
src/ast_render.cpp | 16 +++++-----
src/codegen.cpp | 4 +--
src/ir.cpp | 59 +++++++++++++++++++-----------------
src/parser.cpp | 26 ++++++++--------
src/tokenizer.cpp | 2 ++
src/tokenizer.hpp | 1 +
9 files changed, 114 insertions(+), 105 deletions(-)
(limited to 'src/analyze.cpp')
diff --git a/doc/langref.html.in b/doc/langref.html.in
index f64170817f..015865ee3b 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1785,7 +1785,7 @@ test "fully anonymous list literal" {
dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"});
}
-fn dump(args: var) void {
+fn dump(args: anytype) void {
assert(args.@"0" == 1234);
assert(args.@"1" == 12.34);
assert(args.@"2");
@@ -2717,7 +2717,7 @@ test "fully anonymous struct" {
});
}
-fn dump(args: var) void {
+fn dump(args: anytype) void {
assert(args.int == 1234);
assert(args.float == 12.34);
assert(args.b);
@@ -4181,14 +4181,14 @@ test "pass struct to function" {
{#header_close#}
{#header_open|Function Parameter Type Inference#}
- Function parameters can be declared with {#syntax#}var{#endsyntax#} in place of the type.
+ Function parameters can be declared with {#syntax#}anytype{#endsyntax#} in place of the type.
In this case the parameter types will be inferred when the function is called.
Use {#link|@TypeOf#} and {#link|@typeInfo#} to get information about the inferred type.
{#code_begin|test#}
const assert = @import("std").debug.assert;
-fn addFortyTwo(x: var) @TypeOf(x) {
+fn addFortyTwo(x: anytype) @TypeOf(x) {
return x + 42;
}
@@ -5974,7 +5974,7 @@ pub fn main() void {
{#code_begin|syntax#}
/// Calls print and then flushes the buffer.
-pub fn printf(self: *OutStream, comptime format: []const u8, args: var) anyerror!void {
+pub fn printf(self: *OutStream, comptime format: []const u8, args: anytype) anyerror!void {
const State = enum {
Start,
OpenBrace,
@@ -6060,7 +6060,7 @@ pub fn printf(self: *OutStream, arg0: i32, arg1: []const u8) !void {
on the type:
{#code_begin|syntax#}
-pub fn printValue(self: *OutStream, value: var) !void {
+pub fn printValue(self: *OutStream, value: anytype) !void {
switch (@typeInfo(@TypeOf(value))) {
.Int => {
return self.printInt(T, value);
@@ -6686,7 +6686,7 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 {
{#header_close#}
{#header_open|@alignCast#}
- {#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}
+ {#syntax#}@alignCast(comptime alignment: u29, ptr: anytype) anytype{#endsyntax#}
{#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
{#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
@@ -6723,7 +6723,7 @@ comptime {
{#header_close#}
{#header_open|@asyncCall#}
-
{#syntax#}@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: var) anyframe->T{#endsyntax#}
+ {#syntax#}@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: anytype) anyframe->T{#endsyntax#}
{#syntax#}@asyncCall{#endsyntax#} performs an {#syntax#}async{#endsyntax#} call on a function pointer,
which may or may not be an {#link|async function|Async Functions#}.
@@ -6811,7 +6811,7 @@ fn func(y: *i32) void {
{#header_close#}
{#header_open|@bitCast#}
- {#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}
+ {#syntax#}@bitCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}
Converts a value of one type to another type.
@@ -6932,7 +6932,7 @@ fn func(y: *i32) void {
{#header_close#}
{#header_open|@call#}
- {#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}
+ {#syntax#}@call(options: std.builtin.CallOptions, function: anytype, args: anytype) anytype{#endsyntax#}
Calls a function, in the same way that invoking an expression with parentheses does:
@@ -7279,7 +7279,7 @@ test "main" {
{#header_close#}
{#header_open|@enumToInt#}
- {#syntax#}@enumToInt(enum_or_tagged_union: var) var{#endsyntax#}
+ {#syntax#}@enumToInt(enum_or_tagged_union: anytype) anytype{#endsyntax#}
Converts an enumeration value into its integer tag type. When a tagged union is passed,
the tag value is used as the enumeration value.
@@ -7314,7 +7314,7 @@ test "main" {
{#header_close#}
{#header_open|@errorToInt#}
-
{#syntax#}@errorToInt(err: var) std.meta.IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}
+ {#syntax#}@errorToInt(err: anytype) std.meta.IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}
Supports the following types:
@@ -7334,7 +7334,7 @@ test "main" {
{#header_close#}
{#header_open|@errSetCast#}
- {#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}
+ {#syntax#}@errSetCast(comptime T: DestType, value: anytype) DestType{#endsyntax#}
Converts an error value from one error set to another error set. Attempting to convert an error
which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
@@ -7342,7 +7342,7 @@ test "main" {
{#header_close#}
{#header_open|@export#}
-
{#syntax#}@export(target: var, comptime options: std.builtin.ExportOptions) void{#endsyntax#}
+ {#syntax#}@export(target: anytype, comptime options: std.builtin.ExportOptions) void{#endsyntax#}
Creates a symbol in the output object file.
@@ -7387,7 +7387,7 @@ export fn @"A function name that is a complete sentence."() void {}
{#header_close#}
{#header_open|@field#}
- {#syntax#}@field(lhs: var, comptime field_name: []const u8) (field){#endsyntax#}
+ {#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}
Performs field access by a compile-time string.
{#code_begin|test#}
@@ -7421,7 +7421,7 @@ test "field access by string" {
{#header_close#}
{#header_open|@floatCast#}
- {#syntax#}@floatCast(comptime DestType: type, value: var) DestType{#endsyntax#}
+ {#syntax#}@floatCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}
Convert from one float type to another. This cast is safe, but may cause the
numeric value to lose precision.
@@ -7429,7 +7429,7 @@ test "field access by string" {
{#header_close#}
{#header_open|@floatToInt#}
-
{#syntax#}@floatToInt(comptime DestType: type, float: var) DestType{#endsyntax#}
+ {#syntax#}@floatToInt(comptime DestType: type, float: anytype) DestType{#endsyntax#}
Converts the integer part of a floating point number to the destination type.
@@ -7455,7 +7455,7 @@ test "field access by string" {
{#header_close#}
{#header_open|@Frame#}
- {#syntax#}@Frame(func: var) type{#endsyntax#}
+ {#syntax#}@Frame(func: anytype) type{#endsyntax#}
This function returns the frame type of a function. This works for {#link|Async Functions#}
as well as any function without a specific calling convention.
@@ -7581,7 +7581,7 @@ test "@hasDecl" {
{#header_close#}
{#header_open|@intCast#}
-
{#syntax#}@intCast(comptime DestType: type, int: var) DestType{#endsyntax#}
+ {#syntax#}@intCast(comptime DestType: type, int: anytype) DestType{#endsyntax#}
Converts an integer to another integer while keeping the same numerical value.
Attempting to convert a number which is out of range of the destination type results in
@@ -7622,7 +7622,7 @@ test "@hasDecl" {
{#header_close#}
{#header_open|@intToFloat#}
-
{#syntax#}@intToFloat(comptime DestType: type, int: var) DestType{#endsyntax#}
+ {#syntax#}@intToFloat(comptime DestType: type, int: anytype) DestType{#endsyntax#}
Converts an integer to the closest floating point representation. To convert the other way, use {#link|@floatToInt#}. This cast is always safe.
@@ -7773,7 +7773,7 @@ test "@wasmMemoryGrow" {
{#header_close#}
{#header_open|@ptrCast#}
- {#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}
+ {#syntax#}@ptrCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}
Converts a pointer of one type to a pointer of another type.
@@ -7784,7 +7784,7 @@ test "@wasmMemoryGrow" {
{#header_close#}
{#header_open|@ptrToInt#}
- {#syntax#}@ptrToInt(value: var) usize{#endsyntax#}
+ {#syntax#}@ptrToInt(value: anytype) usize{#endsyntax#}
Converts {#syntax#}value{#endsyntax#} to a {#syntax#}usize{#endsyntax#} which is the address of the pointer. {#syntax#}value{#endsyntax#} can be one of these types:
@@ -8042,7 +8042,7 @@ test "@setRuntimeSafety" {
{#header_close#}
{#header_open|@splat#}
- {#syntax#}@splat(comptime len: u32, scalar: var) std.meta.Vector(len, @TypeOf(scalar)){#endsyntax#}
+ {#syntax#}@splat(comptime len: u32, scalar: anytype) std.meta.Vector(len, @TypeOf(scalar)){#endsyntax#}
Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
{#syntax#}scalar{#endsyntax#}:
@@ -8088,7 +8088,7 @@ fn doTheTest() void {
{#code_end#}
{#header_close#}
{#header_open|@sqrt#}
-
{#syntax#}@sqrt(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@sqrt(value: anytype) @TypeOf(value){#endsyntax#}
Performs the square root of a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8099,7 +8099,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@sin#}
- {#syntax#}@sin(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@sin(value: anytype) @TypeOf(value){#endsyntax#}
Sine trigometric function on a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8110,7 +8110,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@cos#}
- {#syntax#}@cos(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@cos(value: anytype) @TypeOf(value){#endsyntax#}
Cosine trigometric function on a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8121,7 +8121,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@exp#}
- {#syntax#}@exp(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@exp(value: anytype) @TypeOf(value){#endsyntax#}
Base-e exponential function on a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8132,7 +8132,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@exp2#}
- {#syntax#}@exp2(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@exp2(value: anytype) @TypeOf(value){#endsyntax#}
Base-2 exponential function on a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8143,7 +8143,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@log#}
- {#syntax#}@log(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@log(value: anytype) @TypeOf(value){#endsyntax#}
Returns the natural logarithm of a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8154,7 +8154,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@log2#}
- {#syntax#}@log2(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@log2(value: anytype) @TypeOf(value){#endsyntax#}
Returns the logarithm to the base 2 of a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8165,7 +8165,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@log10#}
- {#syntax#}@log10(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@log10(value: anytype) @TypeOf(value){#endsyntax#}
Returns the logarithm to the base 10 of a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8176,7 +8176,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@fabs#}
- {#syntax#}@fabs(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@fabs(value: anytype) @TypeOf(value){#endsyntax#}
Returns the absolute value of a floating point number. Uses a dedicated hardware instruction
when available.
@@ -8187,7 +8187,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@floor#}
- {#syntax#}@floor(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@floor(value: anytype) @TypeOf(value){#endsyntax#}
Returns the largest integral value not greater than the given floating point number.
Uses a dedicated hardware instruction when available.
@@ -8198,7 +8198,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@ceil#}
- {#syntax#}@ceil(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@ceil(value: anytype) @TypeOf(value){#endsyntax#}
Returns the largest integral value not less than the given floating point number.
Uses a dedicated hardware instruction when available.
@@ -8209,7 +8209,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@trunc#}
- {#syntax#}@trunc(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@trunc(value: anytype) @TypeOf(value){#endsyntax#}
Rounds the given floating point number to an integer, towards zero.
Uses a dedicated hardware instruction when available.
@@ -8220,7 +8220,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@round#}
- {#syntax#}@round(value: var) @TypeOf(value){#endsyntax#}
+ {#syntax#}@round(value: anytype) @TypeOf(value){#endsyntax#}
Rounds the given floating point number to an integer, away from zero. Uses a dedicated hardware instruction
when available.
@@ -8241,7 +8241,7 @@ fn doTheTest() void {
{#header_close#}
{#header_open|@tagName#}
-
{#syntax#}@tagName(value: var) []const u8{#endsyntax#}
+ {#syntax#}@tagName(value: anytype) []const u8{#endsyntax#}
Converts an enum value or union value to a slice of bytes representing the name.
If the enum is non-exhaustive and the tag value does not map to a name, it invokes safety-checked {#link|Undefined Behavior#}.
@@ -8292,7 +8292,7 @@ fn List(comptime T: type) type {
{#header_close#}
{#header_open|@truncate#}
- {#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}
+ {#syntax#}@truncate(comptime T: type, integer: anytype) T{#endsyntax#}
This function truncates bits from an integer type, resulting in a smaller
or same-sized integer type.
@@ -10214,7 +10214,7 @@ TopLevelDecl
/ (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
/ KEYWORD_usingnamespace Expr SEMICOLON
-FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
+FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_anytype / TypeExpr)
VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
@@ -10386,7 +10386,7 @@ LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
ParamType
- <- KEYWORD_var
+ <- KEYWORD_anytype
/ DOT3
/ TypeExpr
@@ -10624,6 +10624,7 @@ KEYWORD_align <- 'align' end_of_word
KEYWORD_allowzero <- 'allowzero' end_of_word
KEYWORD_and <- 'and' end_of_word
KEYWORD_anyframe <- 'anyframe' end_of_word
+KEYWORD_anytype <- 'anytype' end_of_word
KEYWORD_asm <- 'asm' end_of_word
KEYWORD_async <- 'async' end_of_word
KEYWORD_await <- 'await' end_of_word
@@ -10669,14 +10670,14 @@ KEYWORD_var <- 'var' end_of_word
KEYWORD_volatile <- 'volatile' end_of_word
KEYWORD_while <- 'while' end_of_word
-keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_asm
- / KEYWORD_async / KEYWORD_await / KEYWORD_break
+keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyframe / KEYWORD_anytype
+ / KEYWORD_allowzero / KEYWORD_asm / KEYWORD_async / KEYWORD_await / KEYWORD_break
/ KEYWORD_catch / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue
/ KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
/ KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false
/ KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline
/ KEYWORD_noalias / KEYWORD_null / KEYWORD_or
- / KEYWORD_orelse / KEYWORD_packed / KEYWORD_anyframe / KEYWORD_pub
+ / KEYWORD_orelse / KEYWORD_packed / KEYWORD_pub
/ KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
/ KEYWORD_struct / KEYWORD_suspend
/ KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 4465bf674c..a73efe2c82 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -692,7 +692,7 @@ enum NodeType {
NodeTypeSuspend,
NodeTypeAnyFrameType,
NodeTypeEnumLiteral,
- NodeTypeVarFieldType,
+ NodeTypeAnyTypeField,
};
enum FnInline {
@@ -705,7 +705,7 @@ struct AstNodeFnProto {
Buf *name;
ZigList params;
AstNode *return_type;
- Token *return_var_token;
+ Token *return_anytype_token;
AstNode *fn_def_node;
// populated if this is an extern declaration
Buf *lib_name;
@@ -734,7 +734,7 @@ struct AstNodeFnDef {
struct AstNodeParamDecl {
Buf *name;
AstNode *type;
- Token *var_token;
+ Token *anytype_token;
Buf doc_comments;
bool is_noalias;
bool is_comptime;
@@ -2145,7 +2145,7 @@ struct CodeGen {
ZigType *entry_num_lit_float;
ZigType *entry_undef;
ZigType *entry_null;
- ZigType *entry_var;
+ ZigType *entry_anytype;
ZigType *entry_global_error_set;
ZigType *entry_enum_literal;
ZigType *entry_any_frame;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index afe0fe6849..5eba515e68 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1129,7 +1129,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *
ZigValue *result = g->pass1_arena->create();
ZigValue *result_ptr = g->pass1_arena->create();
result->special = ConstValSpecialUndef;
- result->type = (type_entry == nullptr) ? g->builtin_types.entry_var : type_entry;
+ result->type = (type_entry == nullptr) ? g->builtin_types.entry_anytype : type_entry;
result_ptr->special = ConstValSpecialStatic;
result_ptr->type = get_pointer_to_type(g, result->type, false);
result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar;
@@ -1230,7 +1230,7 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_opaque_type) {
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
- if (type_val->data.x_type == g->builtin_types.entry_var) {
+ if (type_val->data.x_type == g->builtin_types.entry_anytype) {
*is_opaque_type = false;
return ErrorNone;
}
@@ -1853,10 +1853,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
buf_sprintf("var args only allowed in functions with C calling convention"));
return g->builtin_types.entry_invalid;
}
- } else if (param_node->data.param_decl.var_token != nullptr) {
+ } else if (param_node->data.param_decl.anytype_token != nullptr) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
add_node_error(g, param_node,
- buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",
+ buf_sprintf("parameter of type 'anytype' not allowed in function with calling convention '%s'",
calling_convention_name(fn_type_id.cc)));
return g->builtin_types.entry_invalid;
}
@@ -1942,10 +1942,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
fn_entry->align_bytes = fn_type_id.alignment;
}
- if (fn_proto->return_var_token != nullptr) {
+ if (fn_proto->return_anytype_token != nullptr) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
add_node_error(g, fn_proto->return_type,
- buf_sprintf("return type 'var' not allowed in function with calling convention '%s'",
+ buf_sprintf("return type 'anytype' not allowed in function with calling convention '%s'",
calling_convention_name(fn_type_id.cc)));
return g->builtin_types.entry_invalid;
}
@@ -3802,7 +3802,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeEnumLiteral:
case NodeTypeAnyFrameType:
case NodeTypeErrorSetField:
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
zig_unreachable();
}
}
@@ -5868,7 +5868,7 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
Error err;
- if (ty == g->builtin_types.entry_var) {
+ if (ty == g->builtin_types.entry_anytype) {
return ReqCompTimeYes;
}
switch (ty->id) {
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 49fad80a40..ad308bf416 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -270,8 +270,8 @@ static const char *node_type_str(NodeType node_type) {
return "EnumLiteral";
case NodeTypeErrorSetField:
return "ErrorSetField";
- case NodeTypeVarFieldType:
- return "VarFieldType";
+ case NodeTypeAnyTypeField:
+ return "AnyTypeField";
}
zig_unreachable();
}
@@ -466,8 +466,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
}
if (param_decl->data.param_decl.is_var_args) {
fprintf(ar->f, "...");
- } else if (param_decl->data.param_decl.var_token != nullptr) {
- fprintf(ar->f, "var");
+ } else if (param_decl->data.param_decl.anytype_token != nullptr) {
+ fprintf(ar->f, "anytype");
} else {
render_node_grouped(ar, param_decl->data.param_decl.type);
}
@@ -496,8 +496,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, ")");
}
- if (node->data.fn_proto.return_var_token != nullptr) {
- fprintf(ar->f, "var");
+ if (node->data.fn_proto.return_anytype_token != nullptr) {
+ fprintf(ar->f, "anytype");
} else {
AstNode *return_type_node = node->data.fn_proto.return_type;
assert(return_type_node != nullptr);
@@ -1216,8 +1216,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str));
break;
}
- case NodeTypeVarFieldType: {
- fprintf(ar->f, "var");
+ case NodeTypeAnyTypeField: {
+ fprintf(ar->f, "anytype");
break;
}
case NodeTypeParamDecl:
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 2f72861bc2..3473a2b0ac 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -8448,8 +8448,8 @@ static void define_builtin_types(CodeGen *g) {
}
{
ZigType *entry = new_type_table_entry(ZigTypeIdOpaque);
- buf_init_from_str(&entry->name, "(var)");
- g->builtin_types.entry_var = entry;
+ buf_init_from_str(&entry->name, "(anytype)");
+ g->builtin_types.entry_anytype = entry;
}
for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
diff --git a/src/ir.cpp b/src/ir.cpp
index ca0fd47c49..6447db8c71 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -9942,7 +9942,7 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
is_var_args = true;
break;
}
- if (param_node->data.param_decl.var_token == nullptr) {
+ if (param_node->data.param_decl.anytype_token == nullptr) {
AstNode *type_node = param_node->data.param_decl.type;
IrInstSrc *type_value = ir_gen_node(irb, type_node, parent_scope);
if (type_value == irb->codegen->invalid_inst_src)
@@ -9968,7 +9968,7 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
}
IrInstSrc *return_type;
- if (node->data.fn_proto.return_var_token == nullptr) {
+ if (node->data.fn_proto.return_anytype_token == nullptr) {
if (node->data.fn_proto.return_type == nullptr) {
return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void);
} else {
@@ -10226,9 +10226,9 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope
add_node_error(irb->codegen, node,
buf_sprintf("inferred array size invalid here"));
return irb->codegen->invalid_inst_src;
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
return ir_lval_wrap(irb, scope,
- ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var), lval, result_loc);
+ ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_anytype), lval, result_loc);
}
zig_unreachable();
}
@@ -10296,7 +10296,7 @@ static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *sco
case NodeTypeSuspend:
case NodeTypeEnumLiteral:
case NodeTypeInferredArrayType:
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
case NodeTypePrefixOpExpr:
add_node_error(irb->codegen, node,
buf_sprintf("invalid left-hand side to assignment"));
@@ -10518,7 +10518,7 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va
if (val == nullptr) return nullptr;
assert(const_val->type->id == ZigTypeIdPointer);
ZigType *expected_type = const_val->type->data.pointer.child_type;
- if (expected_type == codegen->builtin_types.entry_var) {
+ if (expected_type == codegen->builtin_types.entry_anytype) {
return val;
}
switch (type_has_one_possible_value(codegen, expected_type)) {
@@ -15040,7 +15040,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
}
// This means the wanted type is anything.
- if (wanted_type == ira->codegen->builtin_types.entry_var) {
+ if (wanted_type == ira->codegen->builtin_types.entry_anytype) {
return value;
}
@@ -15635,7 +15635,7 @@ static IrInstGen *ir_implicit_cast(IrAnalyze *ira, IrInstGen *value, ZigType *ex
static ZigType *get_ptr_elem_type(CodeGen *g, IrInstGen *ptr) {
ir_assert_gen(ptr->value->type->id == ZigTypeIdPointer, ptr);
ZigType *elem_type = ptr->value->type->data.pointer.child_type;
- if (elem_type != g->builtin_types.entry_var)
+ if (elem_type != g->builtin_types.entry_anytype)
return elem_type;
if (ir_resolve_lazy(g, ptr->base.source_node, ptr->value))
@@ -15687,7 +15687,7 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns
}
if (ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
ZigValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr->value);
- if (child_type == ira->codegen->builtin_types.entry_var) {
+ if (child_type == ira->codegen->builtin_types.entry_anytype) {
child_type = pointee->type;
}
if (pointee->special != ConstValSpecialRuntime) {
@@ -19087,7 +19087,7 @@ static Error ir_result_has_type(IrAnalyze *ira, ResultLoc *result_loc, bool *out
ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child);
if (type_is_invalid(dest_type))
return ErrorSemanticAnalyzeFail;
- *out = (dest_type != ira->codegen->builtin_types.entry_var);
+ *out = (dest_type != ira->codegen->builtin_types.entry_anytype);
return ErrorNone;
}
case ResultLocIdVar:
@@ -19293,7 +19293,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
if (type_is_invalid(dest_type))
return ira->codegen->invalid_inst_gen;
- if (dest_type == ira->codegen->builtin_types.entry_var) {
+ if (dest_type == ira->codegen->builtin_types.entry_anytype) {
return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type);
}
@@ -19439,7 +19439,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
return ira->codegen->invalid_inst_gen;
}
- if (child_type != ira->codegen->builtin_types.entry_var) {
+ if (child_type != ira->codegen->builtin_types.entry_anytype) {
if (type_size(ira->codegen, child_type) != type_size(ira->codegen, value_type)) {
// pointer cast won't work; we need a temporary location.
result_bit_cast->parent->written = parent_was_written;
@@ -19600,9 +19600,9 @@ static IrInstGen *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstSr
if (type_is_invalid(implicit_elem_type))
return ira->codegen->invalid_inst_gen;
} else {
- implicit_elem_type = ira->codegen->builtin_types.entry_var;
+ implicit_elem_type = ira->codegen->builtin_types.entry_anytype;
}
- if (implicit_elem_type == ira->codegen->builtin_types.entry_var) {
+ if (implicit_elem_type == ira->codegen->builtin_types.entry_anytype) {
Buf *bare_name = buf_alloc();
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
instruction->base.base.scope, instruction->base.base.source_node, bare_name);
@@ -19759,7 +19759,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
assert(param_decl_node->type == NodeTypeParamDecl);
IrInstGen *casted_arg;
- if (param_decl_node->data.param_decl.var_token == nullptr) {
+ if (param_decl_node->data.param_decl.anytype_token == nullptr) {
AstNode *param_type_node = param_decl_node->data.param_decl.type;
ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node);
if (type_is_invalid(param_type))
@@ -19799,7 +19799,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
arg_part_of_generic_id = true;
casted_arg = arg;
} else {
- if (param_decl_node->data.param_decl.var_token == nullptr) {
+ if (param_decl_node->data.param_decl.anytype_token == nullptr) {
AstNode *param_type_node = param_decl_node->data.param_decl.type;
ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node);
if (type_is_invalid(param_type))
@@ -20011,7 +20011,7 @@ static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr,
}
if (ptr->value->type->data.pointer.inferred_struct_field != nullptr &&
- child_type == ira->codegen->builtin_types.entry_var)
+ child_type == ira->codegen->builtin_types.entry_anytype)
{
child_type = ptr->value->type->data.pointer.inferred_struct_field->inferred_struct_type;
}
@@ -20202,6 +20202,11 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
}
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
+ if (return_type_node == nullptr) {
+ ir_add_error(ira, &fn_ref->base,
+ buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
+ return ira->codegen->invalid_inst_gen;
+ }
ZigType *specified_return_type = ir_analyze_type_expr(ira, exec_scope, return_type_node);
if (type_is_invalid(specified_return_type))
return ira->codegen->invalid_inst_gen;
@@ -20364,7 +20369,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
inst_fn_type_id.alignment = align_bytes;
}
- if (fn_proto_node->data.fn_proto.return_var_token == nullptr) {
+ if (fn_proto_node->data.fn_proto.return_anytype_token == nullptr) {
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node);
if (type_is_invalid(specified_return_type))
@@ -20463,7 +20468,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
if (type_is_invalid(dummy_result->value->type))
return ira->codegen->invalid_inst_gen;
ZigType *res_child_type = result_loc->value->type->data.pointer.child_type;
- if (res_child_type == ira->codegen->builtin_types.entry_var) {
+ if (res_child_type == ira->codegen->builtin_types.entry_anytype) {
res_child_type = impl_fn_type_id->return_type;
}
if (!handle_is_ptr(ira->codegen, res_child_type)) {
@@ -20606,7 +20611,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
if (type_is_invalid(dummy_result->value->type))
return ira->codegen->invalid_inst_gen;
ZigType *res_child_type = result_loc->value->type->data.pointer.child_type;
- if (res_child_type == ira->codegen->builtin_types.entry_var) {
+ if (res_child_type == ira->codegen->builtin_types.entry_anytype) {
res_child_type = return_type;
}
if (!handle_is_ptr(ira->codegen, res_child_type)) {
@@ -22337,7 +22342,7 @@ static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
inferred_struct_field->inferred_struct_type = container_type;
inferred_struct_field->field_name = field_name;
- ZigType *elem_type = ira->codegen->builtin_types.entry_var;
+ ZigType *elem_type = ira->codegen->builtin_types.entry_anytype;
ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,
PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);
@@ -25115,7 +25120,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_ent
fields[5]->special = ConstValSpecialStatic;
fields[5]->type = ira->codegen->builtin_types.entry_bool;
fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;
- // sentinel: var
+ // sentinel: anytype
ensure_field_index(result->type, "sentinel", 6);
fields[6]->special = ConstValSpecialStatic;
if (attrs_type->data.pointer.child_type->id != ZigTypeIdOpaque) {
@@ -25243,7 +25248,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
fields[1]->special = ConstValSpecialStatic;
fields[1]->type = ira->codegen->builtin_types.entry_type;
fields[1]->data.x_type = type_entry->data.array.child_type;
- // sentinel: var
+ // sentinel: anytype
fields[2]->special = ConstValSpecialStatic;
fields[2]->type = get_optional_type(ira->codegen, type_entry->data.array.child_type);
fields[2]->data.x_optional = type_entry->data.array.sentinel;
@@ -25598,7 +25603,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
inner_fields[2]->data.x_type = struct_field->type_entry;
- // default_value: var
+ // default_value: anytype
inner_fields[3]->special = ConstValSpecialStatic;
inner_fields[3]->type = get_optional_type2(ira->codegen, struct_field->type_entry);
if (inner_fields[3]->type == nullptr) return ErrorSemanticAnalyzeFail;
@@ -25736,7 +25741,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
result->data.x_struct.fields = fields;
ZigFn *fn = type_entry->data.frame.fn;
- // function: var
+ // function: anytype
ensure_field_index(result->type, "function", 0);
fields[0] = create_const_fn(ira->codegen, fn);
break;
@@ -29996,7 +30001,7 @@ static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgTy
if (arg_index >= fn_type_id->param_count) {
if (instruction->allow_var) {
// TODO remove this with var args
- return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_var);
+ return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_anytype);
}
ir_add_error(ira, &arg_index_inst->base,
buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " arguments",
@@ -30010,7 +30015,7 @@ static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgTy
ir_assert(fn_type->data.fn.is_generic, &instruction->base.base);
if (instruction->allow_var) {
- return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_var);
+ return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_anytype);
} else {
ir_add_error(ira, &arg_index_inst->base,
buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic",
diff --git a/src/parser.cpp b/src/parser.cpp
index c6c5823672..fcd1133b0d 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -786,7 +786,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B
return nullptr;
}
-// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
+// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_anytype / TypeExpr)
static AstNode *ast_parse_fn_proto(ParseContext *pc) {
Token *first = eat_token_if(pc, TokenIdKeywordFn);
if (first == nullptr) {
@@ -801,10 +801,10 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
AstNode *align_expr = ast_parse_byte_align(pc);
AstNode *section_expr = ast_parse_link_section(pc);
AstNode *callconv_expr = ast_parse_callconv(pc);
- Token *var = eat_token_if(pc, TokenIdKeywordVar);
+ Token *anytype = eat_token_if(pc, TokenIdKeywordAnyType);
Token *exmark = nullptr;
AstNode *return_type = nullptr;
- if (var == nullptr) {
+ if (anytype == nullptr) {
exmark = eat_token_if(pc, TokenIdBang);
return_type = ast_expect(pc, ast_parse_type_expr);
}
@@ -816,7 +816,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
res->data.fn_proto.align_expr = align_expr;
res->data.fn_proto.section_expr = section_expr;
res->data.fn_proto.callconv_expr = callconv_expr;
- res->data.fn_proto.return_var_token = var;
+ res->data.fn_proto.return_anytype_token = anytype;
res->data.fn_proto.auto_err_set = exmark != nullptr;
res->data.fn_proto.return_type = return_type;
@@ -870,9 +870,9 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
AstNode *type_expr = nullptr;
if (eat_token_if(pc, TokenIdColon) != nullptr) {
- Token *var_tok = eat_token_if(pc, TokenIdKeywordVar);
- if (var_tok != nullptr) {
- type_expr = ast_create_node(pc, NodeTypeVarFieldType, var_tok);
+ Token *anytype_tok = eat_token_if(pc, TokenIdKeywordAnyType);
+ if (anytype_tok != nullptr) {
+ type_expr = ast_create_node(pc, NodeTypeAnyTypeField, anytype_tok);
} else {
type_expr = ast_expect(pc, ast_parse_type_expr);
}
@@ -2191,14 +2191,14 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) {
}
// ParamType
-// <- KEYWORD_var
+// <- KEYWORD_anytype
// / DOT3
// / TypeExpr
static AstNode *ast_parse_param_type(ParseContext *pc) {
- Token *var_token = eat_token_if(pc, TokenIdKeywordVar);
- if (var_token != nullptr) {
- AstNode *res = ast_create_node(pc, NodeTypeParamDecl, var_token);
- res->data.param_decl.var_token = var_token;
+ Token *anytype_token = eat_token_if(pc, TokenIdKeywordAnyType);
+ if (anytype_token != nullptr) {
+ AstNode *res = ast_create_node(pc, NodeTypeParamDecl, anytype_token);
+ res->data.param_decl.anytype_token = anytype_token;
return res;
}
@@ -3207,7 +3207,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.suspend.block, visit, context);
break;
case NodeTypeEnumLiteral:
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
break;
}
}
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index f09a146f2b..487a125d62 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -106,6 +106,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"allowzero", TokenIdKeywordAllowZero},
{"and", TokenIdKeywordAnd},
{"anyframe", TokenIdKeywordAnyFrame},
+ {"anytype", TokenIdKeywordAnyType},
{"asm", TokenIdKeywordAsm},
{"async", TokenIdKeywordAsync},
{"await", TokenIdKeywordAwait},
@@ -1569,6 +1570,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordAlign: return "align";
case TokenIdKeywordAnd: return "and";
case TokenIdKeywordAnyFrame: return "anyframe";
+ case TokenIdKeywordAnyType: return "anytype";
case TokenIdKeywordAsm: return "asm";
case TokenIdKeywordBreak: return "break";
case TokenIdKeywordCatch: return "catch";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index 552ded4ef8..d8af21ee00 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -54,6 +54,7 @@ enum TokenId {
TokenIdKeywordAllowZero,
TokenIdKeywordAnd,
TokenIdKeywordAnyFrame,
+ TokenIdKeywordAnyType,
TokenIdKeywordAsm,
TokenIdKeywordAsync,
TokenIdKeywordAwait,
--
cgit v1.2.3
From be1507a7afe4c8869abdbab67a32ede6afe3d938 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Sat, 11 Jul 2020 22:04:38 +0300
Subject: update compile error tests and some doc comments
---
doc/docgen.zig | 11 +++++-----
lib/std/fmt.zig | 2 +-
lib/std/io/serialization.zig | 48 ++++++++++++++++++++++++--------------------
lib/std/log.zig | 2 +-
lib/std/zig/ast.zig | 4 ++--
src-self-hosted/Module.zig | 2 +-
src/analyze.cpp | 4 ++--
test/compile_errors.zig | 34 +++++++++++++++----------------
8 files changed, 56 insertions(+), 51 deletions(-)
(limited to 'src/analyze.cpp')
diff --git a/doc/docgen.zig b/doc/docgen.zig
index e2acfae768..af4d2530d0 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -212,7 +212,7 @@ const Tokenizer = struct {
}
};
-fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: var) anyerror {
+fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: anytype) anyerror {
const loc = tokenizer.getTokenLocation(token);
const args_prefix = .{ tokenizer.source_file_name, loc.line + 1, loc.column + 1 };
warn("{}:{}:{}: error: " ++ fmt ++ "\n", args_prefix ++ args);
@@ -634,7 +634,7 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {
return buf.toOwnedSlice();
}
-fn writeEscaped(out: var, input: []const u8) !void {
+fn writeEscaped(out: anytype, input: []const u8) !void {
for (input) |c| {
try switch (c) {
'&' => out.writeAll("&"),
@@ -765,7 +765,7 @@ fn isType(name: []const u8) bool {
return false;
}
-fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Token, raw_src: []const u8) !void {
+fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: anytype, source_token: Token, raw_src: []const u8) !void {
const src = mem.trim(u8, raw_src, " \n");
try out.writeAll("");
var tokenizer = std.zig.Tokenizer.init(src);
@@ -825,6 +825,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.Keyword_volatile,
.Keyword_allowzero,
.Keyword_while,
+ .Keyword_anytype,
=> {
try out.writeAll("");
try writeEscaped(out, src[token.loc.start..token.loc.end]);
@@ -977,12 +978,12 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
try out.writeAll("");
}
-fn tokenizeAndPrint(docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void {
+fn tokenizeAndPrint(docgen_tokenizer: *Tokenizer, out: anytype, source_token: Token) !void {
const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end];
return tokenizeAndPrintRaw(docgen_tokenizer, out, source_token, raw_src);
}
-fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void {
+fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: anytype, zig_exe: []const u8) !void {
var code_progress_index: usize = 0;
var env_map = try process.getEnvMap(allocator);
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index 7415b1b520..7e288170af 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -69,7 +69,7 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
///
/// If a formatted user type contains a function of the type
/// ```
-/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: var) !void
+/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void
/// ```
/// with `?` being the type formatted, this function will be called instead of the default implementation.
/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
diff --git a/lib/std/io/serialization.zig b/lib/std/io/serialization.zig
index 8fe0782c84..317dde6417 100644
--- a/lib/std/io/serialization.zig
+++ b/lib/std/io/serialization.zig
@@ -16,14 +16,16 @@ pub const Packing = enum {
};
/// Creates a deserializer that deserializes types from any stream.
-/// If `is_packed` is true, the data stream is treated as bit-packed,
-/// otherwise data is expected to be packed to the smallest byte.
-/// Types may implement a custom deserialization routine with a
-/// function named `deserialize` in the form of:
-/// pub fn deserialize(self: *Self, deserializer: var) !void
-/// which will be called when the deserializer is used to deserialize
-/// that type. It will pass a pointer to the type instance to deserialize
-/// into and a pointer to the deserializer struct.
+/// If `is_packed` is true, the data stream is treated as bit-packed,
+/// otherwise data is expected to be packed to the smallest byte.
+/// Types may implement a custom deserialization routine with a
+/// function named `deserialize` in the form of:
+/// ```
+/// pub fn deserialize(self: *Self, deserializer: anytype) !void
+/// ```
+/// which will be called when the deserializer is used to deserialize
+/// that type. It will pass a pointer to the type instance to deserialize
+/// into and a pointer to the deserializer struct.
pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, comptime ReaderType: type) type {
return struct {
in_stream: if (packing == .Bit) io.BitReader(endian, ReaderType) else ReaderType,
@@ -108,7 +110,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
const C = comptime meta.Child(T);
const child_type_id = @typeInfo(C);
- //custom deserializer: fn(self: *Self, deserializer: var) !void
+ //custom deserializer: fn(self: *Self, deserializer: anytype) !void
if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self);
if (comptime trait.isPacked(C) and packing != .Bit) {
@@ -196,18 +198,20 @@ pub fn deserializer(
}
/// Creates a serializer that serializes types to any stream.
-/// If `is_packed` is true, the data will be bit-packed into the stream.
-/// Note that the you must call `serializer.flush()` when you are done
-/// writing bit-packed data in order ensure any unwritten bits are committed.
-/// If `is_packed` is false, data is packed to the smallest byte. In the case
-/// of packed structs, the struct will written bit-packed and with the specified
-/// endianess, after which data will resume being written at the next byte boundary.
-/// Types may implement a custom serialization routine with a
-/// function named `serialize` in the form of:
-/// pub fn serialize(self: Self, serializer: var) !void
-/// which will be called when the serializer is used to serialize that type. It will
-/// pass a const pointer to the type instance to be serialized and a pointer
-/// to the serializer struct.
+/// If `is_packed` is true, the data will be bit-packed into the stream.
+/// Note that the you must call `serializer.flush()` when you are done
+/// writing bit-packed data in order ensure any unwritten bits are committed.
+/// If `is_packed` is false, data is packed to the smallest byte. In the case
+/// of packed structs, the struct will written bit-packed and with the specified
+/// endianess, after which data will resume being written at the next byte boundary.
+/// Types may implement a custom serialization routine with a
+/// function named `serialize` in the form of:
+/// ```
+/// pub fn serialize(self: Self, serializer: anytype) !void
+/// ```
+/// which will be called when the serializer is used to serialize that type. It will
+/// pass a const pointer to the type instance to be serialized and a pointer
+/// to the serializer struct.
pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, comptime OutStreamType: type) type {
return struct {
out_stream: if (packing == .Bit) io.BitOutStream(endian, OutStreamType) else OutStreamType,
@@ -270,7 +274,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
return;
}
- //custom serializer: fn(self: Self, serializer: var) !void
+ //custom serializer: fn(self: Self, serializer: anytype) !void
if (comptime trait.hasFn("serialize")(T)) return T.serialize(value, self);
if (comptime trait.isPacked(T) and packing != .Bit) {
diff --git a/lib/std/log.zig b/lib/std/log.zig
index 0006580031..3fb75b7e37 100644
--- a/lib/std/log.zig
+++ b/lib/std/log.zig
@@ -22,7 +22,7 @@ const root = @import("root");
//! comptime level: std.log.Level,
//! comptime scope: @TypeOf(.EnumLiteral),
//! comptime format: []const u8,
-//! args: var,
+//! args: anytype,
//! ) void {
//! // Ignore all non-critical logging from sources other than
//! // .my_project and .nice_library
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index 7cb4936444..0502f5bb64 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -1052,12 +1052,12 @@ pub const Node = struct {
const params_len: usize = if (self.params_len == 0)
0
else switch (self.paramsConst()[self.params_len - 1].param_type) {
- .var_type, .type_expr => self.params_len,
+ .any_type, .type_expr => self.params_len,
.var_args => self.params_len - 1,
};
if (i < params_len) {
switch (self.paramsConst()[i].param_type) {
- .var_type => |n| return n,
+ .any_type => |n| return n,
.var_args => unreachable,
.type_expr => |n| return n,
}
diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig
index b0678ea665..d173bd36e8 100644
--- a/src-self-hosted/Module.zig
+++ b/src-self-hosted/Module.zig
@@ -1132,7 +1132,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
const param_types = try fn_type_scope.arena.alloc(*zir.Inst, param_decls.len);
for (param_decls) |param_decl, i| {
const param_type_node = switch (param_decl.param_type) {
- .var_type => |node| return self.failNode(&fn_type_scope.base, node, "TODO implement anytype parameter", .{}),
+ .any_type => |node| return self.failNode(&fn_type_scope.base, node, "TODO implement anytype parameter", .{}),
.var_args => |tok| return self.failTok(&fn_type_scope.base, tok, "TODO implement var args", .{}),
.type_expr => |node| node,
};
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 5eba515e68..67c900507d 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1511,13 +1511,13 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
}
for (; i < fn_type_id->param_count; i += 1) {
const char *comma_str = (i == 0) ? "" : ",";
- buf_appendf(&fn_type->name, "%svar", comma_str);
+ buf_appendf(&fn_type->name, "%sanytype", comma_str);
}
buf_append_str(&fn_type->name, ")");
if (fn_type_id->cc != CallingConventionUnspecified) {
buf_appendf(&fn_type->name, " callconv(.%s)", calling_convention_name(fn_type_id->cc));
}
- buf_append_str(&fn_type->name, " var");
+ buf_append_str(&fn_type->name, " anytype");
fn_type->data.fn.fn_type_id = *fn_type_id;
fn_type->data.fn.is_generic = true;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index df2e759bf1..fb4428fbc6 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -42,7 +42,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\fn foo() Foo {
\\ return .{ .x = 42 };
\\}
- \\fn bar(val: var) Foo {
+ \\fn bar(val: anytype) Foo {
\\ return .{ .x = val };
\\}
\\export fn entry() void {
@@ -1034,7 +1034,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ storev(&v[i], 42);
\\}
\\
- \\fn storev(ptr: var, val: i32) void {
+ \\fn storev(ptr: anytype, val: i32) void {
\\ ptr.* = val;
\\}
, &[_][]const u8{
@@ -1049,7 +1049,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var x = loadv(&v[i]);
\\}
\\
- \\fn loadv(ptr: var) i32 {
+ \\fn loadv(ptr: anytype) i32 {
\\ return ptr.*;
\\}
, &[_][]const u8{
@@ -1832,7 +1832,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ while (true) {}
\\}
, &[_][]const u8{
- "error: expected type 'fn([]const u8, ?*std.builtin.StackTrace) noreturn', found 'fn([]const u8,var) var'",
+ "error: expected type 'fn([]const u8, ?*std.builtin.StackTrace) noreturn', found 'fn([]const u8,anytype) anytype'",
"note: only one of the functions is generic",
});
@@ -2032,11 +2032,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add("export generic function",
- \\export fn foo(num: var) i32 {
+ \\export fn foo(num: anytype) i32 {
\\ return 0;
\\}
, &[_][]const u8{
- "tmp.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'C'",
+ "tmp.zig:1:15: error: parameter of type 'anytype' not allowed in function with calling convention 'C'",
});
cases.add("C pointer to c_void",
@@ -2836,7 +2836,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add("missing parameter name of generic function",
- \\fn dump(var) void {}
+ \\fn dump(anytype) void {}
\\export fn entry() void {
\\ var a: u8 = 9;
\\ dump(a);
@@ -2859,13 +2859,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add("generic fn as parameter without comptime keyword",
- \\fn f(_: fn (var) void) void {}
- \\fn g(_: var) void {}
+ \\fn f(_: fn (anytype) void) void {}
+ \\fn g(_: anytype) void {}
\\export fn entry() void {
\\ f(g);
\\}
, &[_][]const u8{
- "tmp.zig:1:9: error: parameter of type 'fn(var) var' must be declared comptime",
+ "tmp.zig:1:9: error: parameter of type 'fn(anytype) anytype' must be declared comptime",
});
cases.add("optional pointer to void in extern struct",
@@ -3165,7 +3165,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add("var makes structs required to be comptime known",
\\export fn entry() void {
- \\ const S = struct{v: var};
+ \\ const S = struct{v: anytype};
\\ var s = S{.v=@as(i32, 10)};
\\}
, &[_][]const u8{
@@ -6072,10 +6072,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add("calling a generic function only known at runtime",
- \\var foos = [_]fn(var) void { foo1, foo2 };
+ \\var foos = [_]fn(anytype) void { foo1, foo2 };
\\
- \\fn foo1(arg: var) void {}
- \\fn foo2(arg: var) void {}
+ \\fn foo1(arg: anytype) void {}
+ \\fn foo2(arg: anytype) void {}
\\
\\pub fn main() !void {
\\ foos[0](true);
@@ -6920,12 +6920,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add("getting return type of generic function",
- \\fn generic(a: var) void {}
+ \\fn generic(a: anytype) void {}
\\comptime {
\\ _ = @TypeOf(generic).ReturnType;
\\}
, &[_][]const u8{
- "tmp.zig:3:25: error: ReturnType has not been resolved because 'fn(var) var' is generic",
+ "tmp.zig:3:25: error: ReturnType has not been resolved because 'fn(anytype) anytype' is generic",
});
cases.add("unsupported modifier at start of asm output constraint",
@@ -7493,7 +7493,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add("issue #5221: invalid struct init type referenced by @typeInfo and passed into function",
- \\fn ignore(comptime param: var) void {}
+ \\fn ignore(comptime param: anytype) void {}
\\
\\export fn foo() void {
\\ const MyStruct = struct {
--
cgit v1.2.3
From 596ca6cf70cf43c27e31bbcfc36bcdc70b13897a Mon Sep 17 00:00:00 2001
From: Vexu
Date: Fri, 17 Jul 2020 20:16:23 +0300
Subject: allow non-pointer extern opaque variables
---
src/analyze.cpp | 11 +++++++----
src/analyze.hpp | 2 +-
src/ir.cpp | 2 +-
test/stage1/behavior/misc.zig | 7 +++++++
4 files changed, 16 insertions(+), 6 deletions(-)
(limited to 'src/analyze.cpp')
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 67c900507d..66f3f28b50 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -3823,15 +3823,18 @@ static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
}
}
-ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry) {
+ZigType *validate_var_type(CodeGen *g, AstNodeVariableDeclaration *source_node, ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
return g->builtin_types.entry_invalid;
+ case ZigTypeIdOpaque:
+ if (source_node->is_extern)
+ return type_entry;
+ ZIG_FALLTHROUGH;
case ZigTypeIdUnreachable:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
- case ZigTypeIdOpaque:
- add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
+ add_node_error(g, source_node->type, buf_sprintf("variable of type '%s' not allowed",
buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
case ZigTypeIdComptimeFloat:
@@ -3973,7 +3976,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
} else {
tld_var->analyzing_type = true;
ZigType *proposed_type = analyze_type_expr(g, tld_var->base.parent_scope, var_decl->type);
- explicit_type = validate_var_type(g, var_decl->type, proposed_type);
+ explicit_type = validate_var_type(g, var_decl, proposed_type);
}
}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index d75c967394..cb58aa6b74 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -77,7 +77,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all
ZigType *get_src_ptr_type(ZigType *type);
uint32_t get_ptr_align(CodeGen *g, ZigType *type);
bool get_ptr_const(CodeGen *g, ZigType *type);
-ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
+ZigType *validate_var_type(CodeGen *g, AstNodeVariableDeclaration *source_node, ZigType *type_entry);
ZigType *container_ref_type(ZigType *type_entry);
bool type_is_complete(ZigType *type_entry);
bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
diff --git a/src/ir.cpp b/src/ir.cpp
index 88e111ccb5..11ff7746e7 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -18505,7 +18505,7 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV
if (decl_var_instruction->var_type != nullptr) {
var_type = decl_var_instruction->var_type->child;
ZigType *proposed_type = ir_resolve_type(ira, var_type);
- explicit_type = validate_var_type(ira->codegen, var_type->base.source_node, proposed_type);
+ explicit_type = validate_var_type(ira->codegen, &var->decl_node->data.variable_declaration, proposed_type);
if (type_is_invalid(explicit_type)) {
var->var_type = ira->codegen->builtin_types.entry_invalid;
return ira->codegen->invalid_inst_gen;
diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig
index 021dbe5602..57a9ba2576 100644
--- a/test/stage1/behavior/misc.zig
+++ b/test/stage1/behavior/misc.zig
@@ -713,3 +713,10 @@ test "auto created variables have correct alignment" {
expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
comptime expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
}
+
+extern var opaque_extern_var: @Type(.Opaque);
+var var_to_export: u32 = 42;
+test "extern variable with non-pointer opaque type" {
+ @export(var_to_export, .{ .name = "opaque_extern_var" });
+ expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
+}
--
cgit v1.2.3