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/ir.cpp | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index f37f91088a..0111a33f34 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25166,9 +25166,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
break;
}
case ZigTypeIdFnFrame:
- ir_add_error(ira, source_instr,
- buf_sprintf("compiler bug: TODO @typeInfo for async function frames. https://github.com/ziglang/zig/issues/3066"));
- return ErrorSemanticAnalyzeFail;
+ {
+ result = ira->codegen->pass1_arena->create();
+ result->special = ConstValSpecialStatic;
+ result->type = ir_type_info_get_type(ira, "Frame", nullptr);
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+ result->data.x_struct.fields = fields;
+ ZigFn *fn = type_entry->data.frame.fn;
+ // function: var
+ ensure_field_index(result->type, "function", 0);
+ fields[0] = create_const_fn(ira->codegen, fn);
+ break;
+ }
}
assert(result != nullptr);
--
cgit v1.2.3
From ca6db2d008cf3e0e3700e84400bd3d6e259e3c0f Mon Sep 17 00:00:00 2001
From: Tadeo Kondrak
Date: Tue, 28 Apr 2020 11:16:11 -0600
Subject: Implement @Type() for EnumLiteral and FnFrame
---
lib/std/builtin.zig | 8 +++++++-
src/ir.cpp | 12 ++++++++++--
test/stage1/behavior/type.zig | 16 ++++++++++++++++
3 files changed, 33 insertions(+), 3 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index af8033ae91..9d419f9af2 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -157,7 +157,7 @@ pub const TypeInfo = union(enum) {
Fn: Fn,
BoundFn: Fn,
Opaque: void,
- Frame: void,
+ Frame: Frame,
AnyFrame: AnyFrame,
Vector: Vector,
EnumLiteral: void,
@@ -315,6 +315,12 @@ pub const TypeInfo = union(enum) {
args: []FnArg,
};
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Frame = struct {
+ function: var,
+ };
+
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const AnyFrame = struct {
diff --git a/src/ir.cpp b/src/ir.cpp
index 0111a33f34..1a7c0c3527 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25446,10 +25446,18 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
ZigType *child_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "child", 0);
return get_any_frame_type(ira->codegen, child_type);
}
+ case ZigTypeIdEnumLiteral:
+ return ira->codegen->builtin_types.entry_enum_literal;
+ case ZigTypeIdFnFrame: {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type == ir_type_info_get_type(ira, "Frame", nullptr));
+ ZigValue *function = get_const_field(ira, source_instr->source_node, payload, "function", 0);
+ assert(function->type->id == ZigTypeIdFn);
+ ZigFn *fn = function->data.x_ptr.data.fn.fn_entry;
+ return get_fn_frame_type(ira->codegen, fn);
+ }
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
- case ZigTypeIdFnFrame:
- case ZigTypeIdEnumLiteral:
ir_add_error(ira, source_instr, buf_sprintf(
"TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
return ira->codegen->invalid_inst_gen->value->type;
diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig
index 2860229cb8..d8ed633887 100644
--- a/test/stage1/behavior/type.zig
+++ b/test/stage1/behavior/type.zig
@@ -213,3 +213,19 @@ test "Type.AnyFrame" {
anyframe->anyframe->u8,
});
}
+
+test "Type.EnumLiteral" {
+ testTypes(&[_]type{
+ @TypeOf(.Dummy),
+ });
+}
+
+fn add(a: i32, b: i32) i32 {
+ return a + b;
+}
+
+test "Type.Frame" {
+ testTypes(&[_]type{
+ @Frame(add),
+ });
+}
--
cgit v1.2.3
From a62e9bc8e50296e2d5b201614a78b0e658887aa9 Mon Sep 17 00:00:00 2001
From: Tadeo Kondrak
Date: Thu, 30 Apr 2020 05:50:17 -0600
Subject: Implement @Type for ErrorSet
---
lib/std/builtin.zig | 1 +
src/ir.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++-
test/stage1/behavior/type.zig | 7 ++++
3 files changed, 81 insertions(+), 1 deletion(-)
(limited to 'src/ir.cpp')
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 9b0293228b..47fba9d095 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -256,6 +256,7 @@ pub const TypeInfo = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Error = struct {
name: []const u8,
+ /// This field is ignored when using @Type().
value: comptime_int,
};
diff --git a/src/ir.cpp b/src/ir.cpp
index 1a7c0c3527..5ba92be3c0 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25456,7 +25456,79 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
ZigFn *fn = function->data.x_ptr.data.fn.fn_entry;
return get_fn_frame_type(ira->codegen, fn);
}
- case ZigTypeIdErrorSet:
+ case ZigTypeIdErrorSet: {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type->id == ZigTypeIdOptional);
+ ZigValue *slice = payload->data.x_optional;
+ if (slice == nullptr)
+ return ira->codegen->builtin_types.entry_global_error_set;
+ assert(slice->special == ConstValSpecialStatic);
+ assert(is_slice(slice->type));
+ ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
+ Buf bare_name = BUF_INIT;
+ buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->old_irb.exec, "error", source_instr->scope, source_instr->source_node, &bare_name));
+ err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
+ err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
+ err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
+ ZigValue *ptr = slice->data.x_struct.fields[slice_ptr_index];
+ assert(ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);;
+ assert(ptr->data.x_ptr.data.base_array.elem_index == 0);
+ ZigValue *arr = ptr->data.x_ptr.data.base_array.array_val;
+ assert(arr->special == ConstValSpecialStatic);
+ assert(arr->data.x_array.special == ConstArraySpecialNone);
+ ZigValue *len = slice->data.x_struct.fields[slice_len_index];
+ size_t count = bigint_as_usize(&len->data.x_bigint);
+ err_set_type->data.error_set.err_count = count;
+ err_set_type->data.error_set.errors = heap::c_allocator.allocate(count);
+ bool *already_set = heap::c_allocator.allocate(ira->codegen->errors_by_index.length + count);
+ for (size_t i = 0; i < count; i++) {
+ ZigValue *error = &arr->data.x_array.data.s_none.elements[i];
+ assert(error->type == ir_type_info_get_type(ira, "Error", nullptr));
+ ErrorTableEntry *err_entry = heap::c_allocator.create();
+ err_entry->decl_node = source_instr->source_node;
+ ZigValue *name_slice = get_const_field(ira, source_instr->source_node, error, "name", 0);
+ ZigValue *name_ptr = name_slice->data.x_struct.fields[slice_ptr_index];
+ ZigValue *name_len = name_slice->data.x_struct.fields[slice_len_index];
+ assert(name_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
+ assert(name_ptr->data.x_ptr.data.base_array.elem_index == 0);
+ ZigValue *name_arr = name_ptr->data.x_ptr.data.base_array.array_val;
+ assert(name_arr->special == ConstValSpecialStatic);
+ switch (name_arr->data.x_array.special) {
+ case ConstArraySpecialUndef:
+ return ira->codegen->invalid_inst_gen->value->type;
+ case ConstArraySpecialNone: {
+ buf_resize(&err_entry->name, 0);
+ size_t name_count = bigint_as_usize(&name_len->data.x_bigint);
+ for (size_t j = 0; j < name_count; j++) {
+ ZigValue *ch_val = &name_arr->data.x_array.data.s_none.elements[j];
+ unsigned ch = bigint_as_u32(&ch_val->data.x_bigint);
+ buf_append_char(&err_entry->name, ch);
+ }
+ break;
+ }
+ case ConstArraySpecialBuf:
+ buf_init_from_buf(&err_entry->name, name_arr->data.x_array.data.s_buf);
+ break;
+ }
+ auto existing_entry = ira->codegen->error_table.put_unique(&err_entry->name, err_entry);
+ if (existing_entry) {
+ err_entry->value = existing_entry->value->value;
+ } else {
+ size_t error_value_count = ira->codegen->errors_by_index.length;
+ assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count));
+ err_entry->value = error_value_count;
+ ira->codegen->errors_by_index.append(err_entry);
+ }
+ if (already_set[err_entry->value]) {
+ ir_add_error(ira, source_instr, buf_sprintf("duplicate error: %s", buf_ptr(&err_entry->name)));
+ return ira->codegen->invalid_inst_gen->value->type;
+ } else {
+ already_set[err_entry->value] = true;
+ }
+ err_set_type->data.error_set.errors[i] = err_entry;
+ }
+ return err_set_type;
+ }
case ZigTypeIdEnum:
ir_add_error(ira, source_instr, buf_sprintf(
"TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig
index d8ed633887..f21e9f1ce9 100644
--- a/test/stage1/behavior/type.zig
+++ b/test/stage1/behavior/type.zig
@@ -229,3 +229,10 @@ test "Type.Frame" {
@Frame(add),
});
}
+
+test "Type.ErrorSet" {
+ // error sets don't compare equal so just check if they compile
+ _ = @Type(@typeInfo(error{}));
+ _ = @Type(@typeInfo(error{A}));
+ _ = @Type(@typeInfo(error{ A, B, C }));
+}
--
cgit v1.2.3
From 2bb3e1aff4976b2d04fb08a46d9221c77da0b204 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 15 Jun 2020 16:48:19 -0400
Subject: stage1: implement type coercion of anon struct literal to struct
closes #3672
---
src/ir.cpp | 146 +++++++++++++++++++++++++++++++++++++---
test/stage1/behavior/struct.zig | 33 +++++++++
2 files changed, 171 insertions(+), 8 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index 887f0a2f9b..d28648e128 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -286,6 +286,7 @@ static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* so
IrInstGen *struct_operand, TypeStructField *field);
static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right);
static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right);
+static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field);
#define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
#define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
@@ -14703,10 +14704,139 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou
}
static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,
- IrInstGen *value, ZigType *wanted_type)
+ IrInstGen *struct_operand, ZigType *wanted_type)
{
- ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to struct"));
- return ira->codegen->invalid_inst_gen;
+ Error err;
+
+ IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false);
+ if (type_is_invalid(struct_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
+ ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_inst_gen;
+
+ size_t actual_field_count = wanted_type->data.structure.src_field_count;
+ size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count;
+
+ bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
+ || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
+ bool is_comptime = true;
+
+ // Determine if the struct_operand will be comptime.
+ // Also emit compile errors for missing fields and duplicate fields.
+ AstNode **field_assign_nodes = heap::c_allocator.allocate(actual_field_count);
+ ZigValue **field_values = heap::c_allocator.allocate(actual_field_count);
+ IrInstGen **casted_fields = heap::c_allocator.allocate(actual_field_count);
+ IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
+
+ for (size_t i = 0; i < instr_field_count; i += 1) {
+ TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i];
+ TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);
+ if (dst_field == nullptr) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'",
+ buf_ptr(src_field->name), buf_ptr(&wanted_type->name)));
+ if (wanted_type->data.structure.decl_node) {
+ add_error_note(ira->codegen, msg, wanted_type->data.structure.decl_node,
+ buf_sprintf("struct '%s' declared here", buf_ptr(&wanted_type->name)));
+ }
+ add_error_note(ira->codegen, msg, src_field->decl_node,
+ buf_sprintf("field '%s' declared here", buf_ptr(src_field->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ir_assert(src_field->decl_node != nullptr, source_instr);
+ AstNode *existing_assign_node = field_assign_nodes[dst_field->src_index];
+ if (existing_assign_node != nullptr) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("duplicate field"));
+ add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here"));
+ return ira->codegen->invalid_inst_gen;
+ }
+ field_assign_nodes[dst_field->src_index] = src_field->decl_node;
+
+ IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
+ struct_operand->value->type, false);
+ if (type_is_invalid(field_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
+ IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
+ if (type_is_invalid(field_value->value->type))
+ return ira->codegen->invalid_inst_gen;
+ IrInstGen *casted_value = ir_implicit_cast(ira, field_value, dst_field->type_entry);
+ if (type_is_invalid(casted_value->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ casted_fields[dst_field->src_index] = casted_value;
+ if (need_comptime || instr_is_comptime(casted_value)) {
+ ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk);
+ if (field_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+ field_val->parent.id = ConstParentIdStruct;
+ field_val->parent.data.p_struct.struct_val = const_result->value;
+ field_val->parent.data.p_struct.field_index = dst_field->src_index;
+ field_values[dst_field->src_index] = field_val;
+ } else {
+ is_comptime = false;
+ }
+ }
+
+ bool any_missing = false;
+ for (size_t i = 0; i < actual_field_count; i += 1) {
+ if (field_assign_nodes[i] != nullptr) continue;
+
+ // look for a default field value
+ TypeStructField *field = wanted_type->data.structure.fields[i];
+ memoize_field_init_val(ira->codegen, wanted_type, field);
+ if (field->init_val == nullptr) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("missing field: '%s'", buf_ptr(field->name)));
+ any_missing = true;
+ continue;
+ }
+ if (type_is_invalid(field->init_val->type))
+ return ira->codegen->invalid_inst_gen;
+ ZigValue *init_val_copy = ira->codegen->pass1_arena->create();
+ copy_const_val(ira->codegen, init_val_copy, field->init_val);
+ init_val_copy->parent.id = ConstParentIdStruct;
+ init_val_copy->parent.data.p_struct.struct_val = const_result->value;
+ init_val_copy->parent.data.p_struct.field_index = i;
+ field_values[i] = init_val_copy;
+ casted_fields[i] = ir_const_move(ira, source_instr, init_val_copy);
+ }
+ if (any_missing)
+ return ira->codegen->invalid_inst_gen;
+
+ if (is_comptime) {
+ heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
+ IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
+ const_result->value->data.x_struct.fields = field_values;
+ return const_result;
+ }
+
+ IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(),
+ wanted_type, nullptr, true, true);
+ if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ for (size_t i = 0; i < actual_field_count; i += 1) {
+ TypeStructField *field = wanted_type->data.structure.fields[i];
+ IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, result_loc_inst, wanted_type, true);
+ if (type_is_invalid(field_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
+ IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, field_ptr, casted_fields[i], true);
+ if (type_is_invalid(store_ptr_inst->value->type))
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
+ heap::c_allocator.deallocate(field_values, actual_field_count);
+ heap::c_allocator.deallocate(casted_fields, actual_field_count);
+
+ return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);
}
static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,
@@ -14727,7 +14857,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou
TypeUnionField *union_field = find_union_type_field(union_type, only_field->name);
if (union_field == nullptr) {
ir_add_error_node(ira, only_field->decl_node,
- buf_sprintf("no member named '%s' in union '%s'",
+ buf_sprintf("no field named '%s' in union '%s'",
buf_ptr(only_field->name), buf_ptr(&union_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -22407,7 +22537,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel
usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error_node(ira, source_node,
- buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
+ buf_sprintf("no field named '%s' in '%s'", buf_ptr(field_name),
buf_ptr(&container_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -23834,7 +23964,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi
TypeUnionField *type_field = find_union_type_field(union_type, field_name);
if (type_field == nullptr) {
ir_add_error_node(ira, field_source_node,
- buf_sprintf("no member named '%s' in union '%s'",
+ buf_sprintf("no field named '%s' in union '%s'",
buf_ptr(field_name), buf_ptr(&union_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -23930,7 +24060,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc
TypeStructField *type_field = find_struct_type_field(container_type, field->name);
if (!type_field) {
ir_add_error_node(ira, field->source_node,
- buf_sprintf("no member named '%s' in struct '%s'",
+ buf_sprintf("no field named '%s' in struct '%s'",
buf_ptr(field->name), buf_ptr(&container_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -23965,7 +24095,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc
memoize_field_init_val(ira->codegen, container_type, field);
if (field->init_val == nullptr) {
ir_add_error(ira, source_instr,
- buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name)));
+ buf_sprintf("missing field: '%s'", buf_ptr(field->name)));
any_missing = true;
continue;
}
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
index 3a4e0a4d93..7b8690d604 100644
--- a/test/stage1/behavior/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -851,3 +851,36 @@ test "struct with union field" {
expectEqual(@as(u32, 2), True.ref);
expectEqual(true, True.kind.Bool);
}
+
+test "type coercion of anon struct literal to struct" {
+ const S = struct {
+ const S2 = struct {
+ A: u32,
+ B: []const u8,
+ C: void,
+ D: Foo = .{},
+ };
+
+ const Foo = struct {
+ field: i32 = 1234,
+ };
+
+ fn doTheTest() void {
+ var y: u32 = 42;
+ const t0 = .{ .A = 123, .B = "foo", .C = {} };
+ const t1 = .{ .A = y, .B = "foo", .C = {} };
+ const y0: S2 = t0;
+ var y1: S2 = t1;
+ expect(y0.A == 123);
+ expect(std.mem.eql(u8, y0.B, "foo"));
+ expect(y0.C == {});
+ expect(y0.D.field == 1234);
+ expect(y1.A == y);
+ expect(std.mem.eql(u8, y1.B, "foo"));
+ expect(y1.C == {});
+ expect(y1.D.field == 1234);
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
--
cgit v1.2.3
From 04c3fae720b57e72dedbaf28982e7e9bfed47db6 Mon Sep 17 00:00:00 2001
From: Jakub Konka
Date: Mon, 15 Jun 2020 17:04:32 +0200
Subject: Remove obsolete branch in ir_analyze_cast
Branch handling `*[N]T` to `E![]T` is already handled in a more complete
branch handling `*[N]T` to `[]T` *and* `*[N]T` to `E![]T` so it seems
safe to remove this one.
---
src/ir.cpp | 40 ----------------------------------------
1 file changed, 40 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index d28648e128..71e3b473b2 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15257,46 +15257,6 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
}
}
- // *[N]T to E![]T
- if (wanted_type->id == ZigTypeIdErrorUnion &&
- is_slice(wanted_type->data.error_union.payload_type) &&
- actual_type->id == ZigTypeIdPointer &&
- actual_type->data.pointer.ptr_len == PtrLenSingle &&
- actual_type->data.pointer.child_type->id == ZigTypeIdArray)
- {
- ZigType *slice_type = wanted_type->data.error_union.payload_type;
- ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
- assert(slice_ptr_type->id == ZigTypeIdPointer);
- ZigType *array_type = actual_type->data.pointer.child_type;
- bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0
- || !actual_type->data.pointer.is_const);
- if (const_ok && types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
- array_type->data.array.child_type, source_node,
- !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
- {
- // If the pointers both have ABI align, it works.
- bool ok_align = slice_ptr_type->data.pointer.explicit_alignment == 0 &&
- actual_type->data.pointer.explicit_alignment == 0;
- if (!ok_align) {
- // If either one has non ABI align, we have to resolve them both
- if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type,
- ResolveStatusAlignmentKnown)))
- {
- return ira->codegen->invalid_inst_gen;
- }
- if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type,
- ResolveStatusAlignmentKnown)))
- {
- return ira->codegen->invalid_inst_gen;
- }
- ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type);
- }
- if (ok_align) {
- return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, nullptr);
- }
- }
- }
-
// @Vector(N,T1) to @Vector(N,T2)
if (actual_type->id == ZigTypeIdVector && wanted_type->id == ZigTypeIdVector) {
if (actual_type->data.vector.len == wanted_type->data.vector.len &&
--
cgit v1.2.3
From 1157ee130732449811294d70021aaafa588d3048 Mon Sep 17 00:00:00 2001
From: antlilja
Date: Wed, 17 Jun 2020 17:35:45 +0200
Subject: Improve builtin op support for f128/comptime_float * Add support for
fabs, floor, ceil, trunc and round * Add behavior tests
---
CMakeLists.txt | 1 +
src/ir.cpp | 21 ++++++--
src/softfloat_ext.cpp | 25 +++++++++
src/softfloat_ext.hpp | 9 ++++
test/stage1/behavior/math.zig | 122 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 173 insertions(+), 5 deletions(-)
create mode 100644 src/softfloat_ext.cpp
create mode 100644 src/softfloat_ext.hpp
(limited to 'src/ir.cpp')
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8599d01a5d..94219c1631 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -288,6 +288,7 @@ set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/target.cpp"
"${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
"${CMAKE_SOURCE_DIR}/src/util.cpp"
+ "${CMAKE_SOURCE_DIR}/src/softfloat_ext.cpp"
"${ZIG_SOURCES_MEM_PROFILE}"
)
set(OPTIMIZED_C_SOURCES
diff --git a/src/ir.cpp b/src/ir.cpp
index d28648e128..8267842671 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -13,6 +13,7 @@
#include "os.hpp"
#include "range_set.hpp"
#include "softfloat.hpp"
+#include "softfloat_ext.hpp"
#include "util.hpp"
#include "mem_list.hpp"
#include "all_types.hpp"
@@ -30303,6 +30304,21 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF
case BuiltinFnIdSqrt:
f128M_sqrt(in, out);
break;
+ case BuiltinFnIdFabs:
+ f128M_abs(in, out);
+ break;
+ case BuiltinFnIdFloor:
+ f128M_roundToInt(in, softfloat_round_min, false, out);
+ break;
+ case BuiltinFnIdCeil:
+ f128M_roundToInt(in, softfloat_round_max, false, out);
+ break;
+ case BuiltinFnIdTrunc:
+ f128M_trunc(in, out);
+ break;
+ case BuiltinFnIdRound:
+ f128M_roundToInt(in, softfloat_round_near_maxMag, false, out);
+ break;
case BuiltinFnIdNearbyInt:
case BuiltinFnIdSin:
case BuiltinFnIdCos:
@@ -30311,11 +30327,6 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF
case BuiltinFnIdLog:
case BuiltinFnIdLog10:
case BuiltinFnIdLog2:
- case BuiltinFnIdFabs:
- case BuiltinFnIdFloor:
- case BuiltinFnIdCeil:
- case BuiltinFnIdTrunc:
- case BuiltinFnIdRound:
return ir_add_error(ira, source_instr,
buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
float_op_to_name(fop), buf_ptr(&float_type->name)));
diff --git a/src/softfloat_ext.cpp b/src/softfloat_ext.cpp
new file mode 100644
index 0000000000..8408a15116
--- /dev/null
+++ b/src/softfloat_ext.cpp
@@ -0,0 +1,25 @@
+#include "softfloat_ext.hpp"
+
+extern "C" {
+ #include "softfloat.h"
+}
+
+void f128M_abs(const float128_t *aPtr, float128_t *zPtr) {
+ float128_t zero_float;
+ ui32_to_f128M(0, &zero_float);
+ if (f128M_lt(aPtr, &zero_float)) {
+ f128M_sub(&zero_float, aPtr, zPtr);
+ } else {
+ *zPtr = *aPtr;
+ }
+}
+
+void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
+ float128_t zero_float;
+ ui32_to_f128M(0, &zero_float);
+ if (f128M_lt(aPtr, &zero_float)) {
+ f128M_roundToInt(aPtr, softfloat_round_max, false, zPtr);
+ } else {
+ f128M_roundToInt(aPtr, softfloat_round_min, false, zPtr);
+ }
+}
\ No newline at end of file
diff --git a/src/softfloat_ext.hpp b/src/softfloat_ext.hpp
new file mode 100644
index 0000000000..0a1f958933
--- /dev/null
+++ b/src/softfloat_ext.hpp
@@ -0,0 +1,9 @@
+#ifndef ZIG_SOFTFLOAT_EXT_HPP
+#define ZIG_SOFTFLOAT_EXT_HPP
+
+#include "softfloat_types.h"
+
+void f128M_abs(const float128_t *aPtr, float128_t *zPtr);
+void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);
+
+#endif
\ No newline at end of file
diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig
index 1d361494eb..b13b1ce1e0 100644
--- a/test/stage1/behavior/math.zig
+++ b/test/stage1/behavior/math.zig
@@ -634,6 +634,128 @@ fn testSqrt(comptime T: type, x: T) void {
expect(@sqrt(x * x) == x);
}
+test "@fabs" {
+ testFabs(f128, 12.0);
+ comptime testFabs(f128, 12.0);
+ testFabs(f64, 12.0);
+ comptime testFabs(f64, 12.0);
+ testFabs(f32, 12.0);
+ comptime testFabs(f32, 12.0);
+ testFabs(f16, 12.0);
+ comptime testFabs(f16, 12.0);
+
+ const x = 14.0;
+ const y = -x;
+ const z = @fabs(y);
+ comptime expectEqual(x, z);
+}
+
+fn testFabs(comptime T: type, x: T) void {
+ const y = -x;
+ const z = @fabs(y);
+ expectEqual(x, z);
+}
+
+test "@floor" {
+ // FIXME: Generates a floorl function call
+ // testFloor(f128, 12.0);
+ comptime testFloor(f128, 12.0);
+ testFloor(f64, 12.0);
+ comptime testFloor(f64, 12.0);
+ testFloor(f32, 12.0);
+ comptime testFloor(f32, 12.0);
+ testFloor(f16, 12.0);
+ comptime testFloor(f16, 12.0);
+
+ const x = 14.0;
+ const y = x + 0.7;
+ const z = @floor(y);
+ comptime expectEqual(x, z);
+}
+
+fn testFloor(comptime T: type, x: T) void {
+ const y = x + 0.6;
+ const z = @floor(y);
+ expectEqual(x, z);
+}
+
+test "@ceil" {
+ // FIXME: Generates a ceill function call
+ //testCeil(f128, 12.0);
+ comptime testCeil(f128, 12.0);
+ testCeil(f64, 12.0);
+ comptime testCeil(f64, 12.0);
+ testCeil(f32, 12.0);
+ comptime testCeil(f32, 12.0);
+ testCeil(f16, 12.0);
+ comptime testCeil(f16, 12.0);
+
+ const x = 14.0;
+ const y = x - 0.7;
+ const z = @ceil(y);
+ comptime expectEqual(x, z);
+}
+
+fn testCeil(comptime T: type, x: T) void {
+ const y = x - 0.8;
+ const z = @ceil(y);
+ expectEqual(x, z);
+}
+
+test "@trunc" {
+ // FIXME: Generates a truncl function call
+ //testTrunc(f128, 12.0);
+ comptime testTrunc(f128, 12.0);
+ testTrunc(f64, 12.0);
+ comptime testTrunc(f64, 12.0);
+ testTrunc(f32, 12.0);
+ comptime testTrunc(f32, 12.0);
+ testTrunc(f16, 12.0);
+ comptime testTrunc(f16, 12.0);
+
+ const x = 14.0;
+ const y = x + 0.7;
+ const z = @trunc(y);
+ comptime expectEqual(x, z);
+}
+
+fn testTrunc(comptime T: type, x: T) void {
+ {
+ const y = x + 0.8;
+ const z = @trunc(y);
+ expectEqual(x, z);
+ }
+
+ {
+ const y = -x - 0.8;
+ const z = @trunc(y);
+ expectEqual(-x, z);
+ }
+}
+
+test "@round" {
+ // FIXME: Generates a roundl function call
+ //testRound(f128, 12.0);
+ comptime testRound(f128, 12.0);
+ testRound(f64, 12.0);
+ comptime testRound(f64, 12.0);
+ testRound(f32, 12.0);
+ comptime testRound(f32, 12.0);
+ testRound(f16, 12.0);
+ comptime testRound(f16, 12.0);
+
+ const x = 14.0;
+ const y = x + 0.4;
+ const z = @round(y);
+ comptime expectEqual(x, z);
+}
+
+fn testRound(comptime T: type, x: T) void {
+ const y = x - 0.5;
+ const z = @round(y);
+ expectEqual(x, z);
+}
+
test "comptime_int param and return" {
const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
expect(a == 137114567242441932203689521744947848950);
--
cgit v1.2.3
From a5379aa3ee376197820f1526c88921607a787a11 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 18 Jun 2020 20:45:48 +0300
Subject: implement `@src`
---
lib/std/builtin.zig | 9 +++++++
src/all_types.hpp | 6 +++++
src/codegen.cpp | 1 +
src/ir.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/ir_print.cpp | 9 +++++++
5 files changed, 101 insertions(+)
(limited to 'src/ir.cpp')
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index af8033ae91..822901be73 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -131,6 +131,15 @@ pub const CallingConvention = enum {
AAPCSVFP,
};
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const SourceLocation = struct {
+ file: []const u8,
+ fn_name: []const u8,
+ line: u32,
+ column: u32,
+};
+
pub const TypeId = @TagType(TypeInfo);
/// This data structure is used by the Zig language code generation and
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 9413ea73a4..88c7e96943 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1827,6 +1827,7 @@ enum BuiltinFnId {
BuiltinFnIdBitSizeof,
BuiltinFnIdWasmMemorySize,
BuiltinFnIdWasmMemoryGrow,
+ BuiltinFnIdSrc,
};
struct BuiltinFnEntry {
@@ -2754,6 +2755,7 @@ enum IrInstSrcId {
IrInstSrcIdSpillEnd,
IrInstSrcIdWasmMemorySize,
IrInstSrcIdWasmMemoryGrow,
+ IrInstSrcIdSrc,
};
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
@@ -3761,6 +3763,10 @@ struct IrInstGenWasmMemoryGrow {
IrInstGen *delta;
};
+struct IrInstSrcSrc {
+ IrInstSrc base;
+};
+
struct IrInstSrcSlice {
IrInstSrc base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index f945dd6545..e20d6d60f5 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -8714,6 +8714,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 1);
create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2);
+ create_builtin_fn(g, BuiltinFnIdSrc, "src", 0);
}
static const char *bool_to_str(bool b) {
diff --git a/src/ir.cpp b/src/ir.cpp
index 71e3b473b2..6406458bf5 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -561,6 +561,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast(inst));
case IrInstSrcIdWasmMemoryGrow:
return heap::c_allocator.destroy(reinterpret_cast(inst));
+ case IrInstSrcIdSrc:
+ return heap::c_allocator.destroy(reinterpret_cast(inst));
}
zig_unreachable();
}
@@ -1627,6 +1629,9 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) {
return IrInstSrcIdWasmMemoryGrow;
}
+static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) {
+ return IrInstSrcIdSrc;
+}
static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) {
return IrInstGenIdDeclVar;
@@ -5030,6 +5035,11 @@ static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_i
return &instruction->base;
}
+static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
+ IrInstSrcSrc *instruction = ir_build_instruction(irb, scope, source_node);
+
+ return &instruction->base;
+}
static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
@@ -7450,6 +7460,11 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node,
lval, result_loc);
}
+ case BuiltinFnIdSrc:
+ {
+ IrInstSrc *src_inst = ir_build_src(irb, scope, node);
+ return ir_lval_wrap(irb, scope, src_inst, lval, result_loc);
+ }
}
zig_unreachable();
}
@@ -30859,6 +30874,64 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil
return ir_build_spill_end_gen(ira, &instruction->base.base, begin, operand->value->type);
}
+static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instruction) {
+ ZigFn *fn_entry = scope_fn_entry(instruction->base.base.scope);
+ if (fn_entry == nullptr) {
+ ir_add_error(ira, &instruction->base.base, buf_sprintf("@src outside function"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigType *u8_ptr = get_pointer_to_type_extra(
+ ira->codegen, ira->codegen->builtin_types.entry_u8,
+ true, false, PtrLenUnknown,
+ 0, 0, 0, false);
+ ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
+
+ ZigType *source_location_type = get_builtin_type(ira->codegen, "SourceLocation");
+ if (type_resolve(ira->codegen, source_location_type, ResolveStatusSizeKnown)) {
+ zig_unreachable();
+ }
+
+ ZigValue *result = ira->codegen->pass1_arena->create();
+ result->special = ConstValSpecialStatic;
+ result->type = source_location_type;
+
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
+ result->data.x_struct.fields = fields;
+
+ // file: []const u8
+ ensure_field_index(source_location_type, "file", 0);
+ fields[0]->special = ConstValSpecialStatic;
+ fields[0]->type = u8_slice;
+
+ ZigType *import = instruction->base.base.source_node->owner;
+ Buf *path = import->data.structure.root_struct->path;
+ ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee;
+ init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true);
+
+ // fn_name: []const u8
+ ensure_field_index(source_location_type, "fn_name", 1);
+ fields[1]->special = ConstValSpecialStatic;
+ fields[1]->type = u8_slice;
+
+ ZigValue *fn_name = create_const_str_lit(ira->codegen, &fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
+ init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true);
+
+ // line: u32
+ ensure_field_index(source_location_type, "line", 2);
+ fields[2]->special = ConstValSpecialStatic;
+ fields[2]->type = ira->codegen->builtin_types.entry_u32;
+ bigint_init_unsigned(&fields[2]->data.x_bigint, instruction->base.base.source_node->line + 1);
+
+ // column: u32
+ ensure_field_index(source_location_type, "column", 3);
+ fields[3]->special = ConstValSpecialStatic;
+ fields[3]->type = ira->codegen->builtin_types.entry_u32;
+ bigint_init_unsigned(&fields[3]->data.x_bigint, instruction->base.base.source_node->column + 1);
+
+ return ir_const_move(ira, &instruction->base.base, result);
+}
+
static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruction) {
switch (instruction->id) {
case IrInstSrcIdInvalid:
@@ -31130,6 +31203,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction);
case IrInstSrcIdWasmMemoryGrow:
return ir_analyze_instruction_wasm_memory_grow(ira, (IrInstSrcWasmMemoryGrow *)instruction);
+ case IrInstSrcIdSrc:
+ return ir_analyze_instruction_src(ira, (IrInstSrcSrc *)instruction);
}
zig_unreachable();
}
@@ -31525,6 +31600,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdAlloca:
case IrInstSrcIdSpillEnd:
case IrInstSrcIdWasmMemorySize:
+ case IrInstSrcIdSrc:
return false;
case IrInstSrcIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index c826d76e03..27bedff47f 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -325,6 +325,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcWasmMemorySize";
case IrInstSrcIdWasmMemoryGrow:
return "SrcWasmMemoryGrow";
+ case IrInstSrcIdSrc:
+ return "SrcSrc";
}
zig_unreachable();
}
@@ -1744,6 +1746,10 @@ static void ir_print_wasm_memory_grow(IrPrintGen *irp, IrInstGenWasmMemoryGrow *
fprintf(irp->f, ")");
}
+static void ir_print_builtin_src(IrPrintSrc *irp, IrInstSrcSrc *instruction) {
+ fprintf(irp->f, "@src()");
+}
+
static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) {
fprintf(irp->f, "@memset(");
ir_print_other_inst_src(irp, instruction->dest_ptr);
@@ -2994,6 +3000,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdWasmMemoryGrow:
ir_print_wasm_memory_grow(irp, (IrInstSrcWasmMemoryGrow *)instruction);
break;
+ case IrInstSrcIdSrc:
+ ir_print_builtin_src(irp, (IrInstSrcSrc *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
--
cgit v1.2.3
From 4a387996311a025a021409f08a61bab9e9885987 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 18 Jun 2020 17:09:10 -0400
Subject: make file and fn_name fields of SourceLocation also null-terminated
One of the main motivating use cases for this language feature is
tracing/profiling tools, which expect null-terminated strings for these
values. Since the data is statically allocated, making them
additionally null-terminated comes at no cost.
This prevents the requirement of compile-time code to convert to
null-termination, which could increase the compilation time of
code with tracing enabled.
See #2029
---
lib/std/builtin.zig | 4 ++--
src/ir.cpp | 12 ++++++------
test/stage1/behavior/src.zig | 2 ++
3 files changed, 10 insertions(+), 8 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 822901be73..195b301840 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -134,8 +134,8 @@ pub const CallingConvention = enum {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const SourceLocation = struct {
- file: []const u8,
- fn_name: []const u8,
+ file: [:0]const u8,
+ fn_name: [:0]const u8,
line: u32,
column: u32,
};
diff --git a/src/ir.cpp b/src/ir.cpp
index 6406458bf5..48e5db8f28 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -30881,10 +30881,10 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr
return ira->codegen->invalid_inst_gen;
}
- ZigType *u8_ptr = get_pointer_to_type_extra(
+ ZigType *u8_ptr = get_pointer_to_type_extra2(
ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown,
- 0, 0, 0, false);
+ 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, ira->codegen->intern.for_zero_byte());
ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
ZigType *source_location_type = get_builtin_type(ira->codegen, "SourceLocation");
@@ -30899,23 +30899,23 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
result->data.x_struct.fields = fields;
- // file: []const u8
+ // file: [:0]const u8
ensure_field_index(source_location_type, "file", 0);
fields[0]->special = ConstValSpecialStatic;
- fields[0]->type = u8_slice;
ZigType *import = instruction->base.base.source_node->owner;
Buf *path = import->data.structure.root_struct->path;
ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true);
+ fields[0]->type = u8_slice;
- // fn_name: []const u8
+ // fn_name: [:0]const u8
ensure_field_index(source_location_type, "fn_name", 1);
fields[1]->special = ConstValSpecialStatic;
- fields[1]->type = u8_slice;
ZigValue *fn_name = create_const_str_lit(ira->codegen, &fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true);
+ fields[1]->type = u8_slice;
// line: u32
ensure_field_index(source_location_type, "line", 2);
diff --git a/test/stage1/behavior/src.zig b/test/stage1/behavior/src.zig
index eec1154374..27fa144e54 100644
--- a/test/stage1/behavior/src.zig
+++ b/test/stage1/behavior/src.zig
@@ -12,4 +12,6 @@ fn doTheTest() void {
expect(src.column == 17);
expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));
expect(std.mem.endsWith(u8, src.file, "src.zig"));
+ expect(src.fn_name[src.fn_name.len] == 0);
+ expect(src.file[src.file.len] == 0);
}
--
cgit v1.2.3
From 8696e52a3d617ce30ec6202adc89cb10c67bcc43 Mon Sep 17 00:00:00 2001
From: Robin Voetter
Date: Sun, 21 Jun 2020 20:55:44 +0200
Subject: Make unary minus for unsigned types a compile error (#5654)
* Make unary minus for unsigned types a compile error
* Add unreachable when generating unsigned negate
---
src/codegen.cpp | 12 ++++++------
src/ir.cpp | 37 ++++++++++++++++++++++---------------
test/compile_errors.zig | 9 +++++++++
3 files changed, 37 insertions(+), 21 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index e20d6d60f5..f7c3575f86 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3540,7 +3540,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executabl
for (size_t field_i = 0; field_i < field_count; field_i += 1) {
TypeEnumField *type_enum_field = &wanted_type->data.enumeration.fields[field_i];
-
+
Buf *name = type_enum_field->name;
auto entry = occupied_tag_values.put_unique(type_enum_field->value, name);
if (entry != nullptr) {
@@ -3654,7 +3654,7 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper
} else if (scalar_type->data.integral.is_signed) {
return LLVMBuildNSWNeg(g->builder, llvm_operand, "");
} else {
- return LLVMBuildNUWNeg(g->builder, llvm_operand, "");
+ zig_unreachable();
}
} else {
zig_unreachable();
@@ -3984,7 +3984,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable,
assert(array_type->data.pointer.child_type->id == ZigTypeIdArray);
array_type = array_type->data.pointer.child_type;
}
-
+
assert(array_type->data.array.len != 0 || array_type->data.array.sentinel != nullptr);
if (safety_check_on) {
@@ -5258,7 +5258,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
for (size_t field_i = 0; field_i < field_count; field_i += 1) {
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
-
+
Buf *name = type_enum_field->name;
auto entry = occupied_tag_values.put_unique(type_enum_field->value, name);
if (entry != nullptr) {
@@ -5471,7 +5471,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) {
}
auto bit_count = operand_type->data.integral.bit_count;
bool is_signed = operand_type->data.integral.is_signed;
-
+
ir_assert(bit_count != 0, instruction);
if (bit_count == 1 || !is_power_of_2(bit_count)) {
return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8));
@@ -9265,7 +9265,7 @@ static void init(CodeGen *g) {
abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32" : "lp64";
}
}
-
+
g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str),
target_specific_cpu_args, target_specific_features, opt_level, reloc_mode,
to_llvm_code_model(g), g->function_sections, float_abi, abi_name);
diff --git a/src/ir.cpp b/src/ir.cpp
index 635af397c4..bb6ca554df 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -12602,28 +12602,28 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (prev_type->id == ZigTypeIdPointer &&
prev_type->data.pointer.ptr_len == PtrLenSingle &&
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
- ((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown)))
+ ((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown)))
{
- prev_inst = cur_inst;
+ prev_inst = cur_inst;
if (prev_type->data.pointer.is_const && !cur_type->data.pointer.is_const) {
// const array pointer and non-const unknown pointer
make_the_pointer_const = true;
}
- continue;
+ continue;
}
// *[N]T to [*]T
if (cur_type->id == ZigTypeIdPointer &&
cur_type->data.pointer.ptr_len == PtrLenSingle &&
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
- ((prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenUnknown)))
+ ((prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenUnknown)))
{
if (cur_type->data.pointer.is_const && !prev_type->data.pointer.is_const) {
// const array pointer and non-const unknown pointer
make_the_pointer_const = true;
}
- continue;
+ continue;
}
// *[N]T to []T
@@ -20987,17 +20987,24 @@ static IrInstGen *ir_analyze_negation(IrAnalyze *ira, IrInstSrcUnOp *instruction
if (type_is_invalid(expr_type))
return ira->codegen->invalid_inst_gen;
- if (!(expr_type->id == ZigTypeIdInt || expr_type->id == ZigTypeIdComptimeInt ||
- expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat ||
- expr_type->id == ZigTypeIdVector))
- {
- ir_add_error(ira, &instruction->base.base,
- buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name)));
- return ira->codegen->invalid_inst_gen;
- }
-
bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
+ switch (expr_type->id) {
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdFloat:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdVector:
+ break;
+ case ZigTypeIdInt:
+ if (is_wrap_op || expr_type->data.integral.is_signed)
+ break;
+ ZIG_FALLTHROUGH;
+ default:
+ ir_add_error(ira, &instruction->base.base,
+ buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
if (instr_is_comptime(value)) {
@@ -30380,7 +30387,7 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF
case BuiltinFnIdTrunc:
f128M_trunc(in, out);
break;
- case BuiltinFnIdRound:
+ case BuiltinFnIdRound:
f128M_roundToInt(in, softfloat_round_near_maxMag, false, out);
break;
case BuiltinFnIdNearbyInt:
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 3f898cc337..e3dd1f0d8f 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -7530,4 +7530,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
, &[_][]const u8{
"tmp.zig:2:9: error: @wasmMemoryGrow is a wasm32 feature only",
});
+
+ cases.add("Issue #5586: Make unary minus for unsigned types a compile error",
+ \\export fn f(x: u32) u32 {
+ \\ const y = -%x;
+ \\ return -y;
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:3:12: error: negation of type 'u32'"
+ });
}
--
cgit v1.2.3
From d907f574e02aadf8196e616bcc2fb2813cf2c82c Mon Sep 17 00:00:00 2001
From: xackus <14938807+xackus@users.noreply.github.com>
Date: Sat, 20 Jun 2020 18:35:01 +0200
Subject: stage1: fix concat of sliced str literals
---
src/ir.cpp | 3 +--
test/stage1/behavior/slice.zig | 5 +++++
2 files changed, 6 insertions(+), 2 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index bb6ca554df..3fa138ed8e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -826,12 +826,11 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_
ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
- // TODO handle sentinel terminated arrays
expand_undef_array(g, array_val);
result = g->pass1_arena->create();
result->special = array_val->special;
result->type = get_array_type(g, array_val->type->data.array.child_type,
- array_val->type->data.array.len - elem_index, nullptr);
+ array_val->type->data.array.len - elem_index, array_val->type->data.array.sentinel);
result->data.x_array.special = ConstArraySpecialNone;
result->data.x_array.data.s_none.elements = &array_val->data.x_array.data.s_none.elements[elem_index];
result->parent.id = ConstParentIdArray;
diff --git a/test/stage1/behavior/slice.zig b/test/stage1/behavior/slice.zig
index 1faefe6800..8aa3bdb7c1 100644
--- a/test/stage1/behavior/slice.zig
+++ b/test/stage1/behavior/slice.zig
@@ -280,6 +280,11 @@ test "slice syntax resulting in pointer-to-array" {
expect(slice[0] == 5);
comptime expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
}
+
+ fn testConcatStrLiterals() void {
+ expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
+ expectEqualSlices("a"[0..:0] ++ "b"[0..:0], "ab");
+ }
};
S.doTheTest();
--
cgit v1.2.3
From 0de35af98b3404f0cf7cd9497f661239d197bbbf Mon Sep 17 00:00:00 2001
From: antlilja
Date: Mon, 22 Jun 2020 12:14:52 +0200
Subject: Add duplicate checking for switch on types * Add compile error tests
---
src/ir.cpp | 32 +++++++++++++++++++++++++++++++-
test/compile_errors.zig | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 1 deletion(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index 3fa138ed8e..01c7936f75 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -28861,7 +28861,37 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
ir_add_error(ira, &instruction->base.base,
buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
return ira->codegen->invalid_inst_gen;
- }
+ } else if(switch_type->id == ZigTypeIdMetaType) {
+ HashMap prevs;
+ // HashMap doubles capacity when reaching 60% capacity,
+ // because we know the size at init we can avoid reallocation by doubling it here
+ prevs.init(instruction->range_count * 2);
+ for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
+ IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i];
+
+ IrInstGen *value = range->start->child;
+ IrInstGen *casted_value = ir_implicit_cast(ira, value, switch_type);
+ if (type_is_invalid(casted_value->value->type)) {
+ prevs.deinit();
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
+ if (!const_expr_val) {
+ prevs.deinit();
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ auto entry = prevs.put_unique(const_expr_val->data.x_type, value);
+ if(entry != nullptr) {
+ ErrorMsg *msg = ir_add_error(ira, &value->base, buf_sprintf("duplicate switch value"));
+ add_error_note(ira->codegen, msg, entry->value->base.source_node, buf_sprintf("previous value is here"));
+ prevs.deinit();
+ return ira->codegen->invalid_inst_gen;
+ }
+ }
+ prevs.deinit();
+ }
return ir_const_void(ira, &instruction->base.base);
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index e3dd1f0d8f..e8b7e610ee 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -4362,6 +4362,40 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:5:14: note: previous value is here",
});
+ cases.add("switch expression - duplicate type",
+ \\fn foo(comptime T: type, x: T) u8 {
+ \\ return switch (T) {
+ \\ u32 => 0,
+ \\ u64 => 1,
+ \\ u32 => 2,
+ \\ else => 3,
+ \\ };
+ \\}
+ \\export fn entry() usize { return @sizeOf(@TypeOf(foo(u32, 0))); }
+ , &[_][]const u8{
+ "tmp.zig:5:9: error: duplicate switch value",
+ "tmp.zig:3:9: note: previous value is here",
+ });
+
+ cases.add("switch expression - duplicate type (struct alias)",
+ \\const Test = struct {
+ \\ bar: i32,
+ \\};
+ \\const Test2 = Test;
+ \\fn foo(comptime T: type, x: T) u8 {
+ \\ return switch (T) {
+ \\ Test => 0,
+ \\ u64 => 1,
+ \\ Test2 => 2,
+ \\ else => 3,
+ \\ };
+ \\}
+ \\export fn entry() usize { return @sizeOf(@TypeOf(foo(u32, 0))); }
+ , &[_][]const u8{
+ "tmp.zig:9:9: error: duplicate switch value",
+ "tmp.zig:7:9: note: previous value is here",
+ });
+
cases.add("switch expression - switch on pointer type with no else",
\\fn foo(x: *u8) void {
\\ switch (x) {
--
cgit v1.2.3
From 50b70bd77f31bba6ffca33b6acb90186e739118e Mon Sep 17 00:00:00 2001
From: Alexandros Naskos
Date: Wed, 24 Jun 2020 14:07:39 +0300
Subject: @asyncCall now requires an argument tuple
---
lib/std/dwarf.zig | 2 +-
lib/std/special/test_runner.zig | 2 +-
lib/std/start.zig | 2 +-
src/all_types.hpp | 15 ++++
src/ir.cpp | 165 ++++++++++++++++++++++++++++++++--------
src/ir_print.cpp | 109 +++++++++++++-------------
6 files changed, 208 insertions(+), 87 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig
index ebb4c096f8..24792c7ca0 100644
--- a/lib/std/dwarf.zig
+++ b/lib/std/dwarf.zig
@@ -359,7 +359,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endia
const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, endian, is_64));
var frame = try allocator.create(F);
defer allocator.destroy(frame);
- return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, endian, is_64);
+ return await @asyncCall(frame, {}, parseFormValue, .{ allocator, in_stream, child_form_id, endian, is_64 });
},
else => error.InvalidDebugInfo,
};
diff --git a/lib/std/special/test_runner.zig b/lib/std/special/test_runner.zig
index 7403cca9c2..828d3165db 100644
--- a/lib/std/special/test_runner.zig
+++ b/lib/std/special/test_runner.zig
@@ -35,7 +35,7 @@ pub fn main() anyerror!void {
async_frame_buffer = try std.heap.page_allocator.alignedAlloc(u8, std.Target.stack_align, size);
}
const casted_fn = @ptrCast(fn () callconv(.Async) anyerror!void, test_fn.func);
- break :blk await @asyncCall(async_frame_buffer, {}, casted_fn);
+ break :blk await @asyncCall(async_frame_buffer, {}, casted_fn, .{});
},
.blocking => {
skip_count += 1;
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 604c22101c..811e05012f 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -214,7 +214,7 @@ inline fn initEventLoopAndCallMain() u8 {
var result: u8 = undefined;
var frame: @Frame(callMainAsync) = undefined;
- _ = @asyncCall(&frame, &result, callMainAsync, loop);
+ _ = @asyncCall(&frame, &result, callMainAsync, .{loop});
loop.run();
return result;
}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 88c7e96943..4465bf674c 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2641,6 +2641,7 @@ enum IrInstSrcId {
IrInstSrcIdCall,
IrInstSrcIdCallArgs,
IrInstSrcIdCallExtra,
+ IrInstSrcIdAsyncCallExtra,
IrInstSrcIdConst,
IrInstSrcIdReturn,
IrInstSrcIdContainerInitList,
@@ -3255,6 +3256,20 @@ struct IrInstSrcCallExtra {
ResultLoc *result_loc;
};
+// This is a pass1 instruction, used by @asyncCall, when the args node
+// is not a literal.
+// `args` is expected to be either a struct or a tuple.
+struct IrInstSrcAsyncCallExtra {
+ IrInstSrc base;
+
+ CallModifier modifier;
+ IrInstSrc *fn_ref;
+ IrInstSrc *ret_ptr;
+ IrInstSrc *new_stack;
+ IrInstSrc *args;
+ ResultLoc *result_loc;
+};
+
struct IrInstGenCall {
IrInstGen base;
diff --git a/src/ir.cpp b/src/ir.cpp
index 01c7936f75..b765ea09ff 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -310,6 +310,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast(inst));
case IrInstSrcIdCallExtra:
return heap::c_allocator.destroy(reinterpret_cast(inst));
+ case IrInstSrcIdAsyncCallExtra:
+ return heap::c_allocator.destroy(reinterpret_cast(inst));
case IrInstSrcIdUnOp:
return heap::c_allocator.destroy(reinterpret_cast(inst));
case IrInstSrcIdCondBr:
@@ -1173,6 +1175,10 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallExtra *) {
return IrInstSrcIdCallExtra;
}
+static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsyncCallExtra *) {
+ return IrInstSrcIdAsyncCallExtra;
+}
+
static constexpr IrInstSrcId ir_inst_id(IrInstSrcConst *) {
return IrInstSrcIdConst;
}
@@ -2442,6 +2448,25 @@ static IrInstSrc *ir_build_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *
return &call_instruction->base;
}
+static IrInstSrc *ir_build_async_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
+ CallModifier modifier, IrInstSrc *fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstSrc *args, ResultLoc *result_loc)
+{
+ IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node);
+ call_instruction->modifier = modifier;
+ call_instruction->fn_ref = fn_ref;
+ call_instruction->ret_ptr = ret_ptr;
+ call_instruction->new_stack = new_stack;
+ call_instruction->args = args;
+ call_instruction->result_loc = result_loc;
+
+ ir_ref_instruction(fn_ref, irb->current_basic_block);
+ if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block);
+ ir_ref_instruction(new_stack, irb->current_basic_block);
+ ir_ref_instruction(args, irb->current_basic_block);
+
+ return &call_instruction->base;
+}
+
static IrInstSrc *ir_build_call_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len,
ResultLoc *result_loc)
@@ -6183,11 +6208,10 @@ static IrInstSrc *ir_gen_this(IrBuilderSrc *irb, Scope *orig_scope, AstNode *nod
static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *await_node, AstNode *call_node,
LVal lval, ResultLoc *result_loc)
{
- size_t arg_offset = 3;
- if (call_node->data.fn_call_expr.params.length < arg_offset) {
+ if (call_node->data.fn_call_expr.params.length != 4) {
add_node_error(irb->codegen, call_node,
- buf_sprintf("expected at least %" ZIG_PRI_usize " arguments, found %" ZIG_PRI_usize,
- arg_offset, call_node->data.fn_call_expr.params.length));
+ buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize,
+ call_node->data.fn_call_expr.params.length));
return irb->codegen->invalid_inst_src;
}
@@ -6206,20 +6230,37 @@ static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *aw
if (fn_ref == irb->codegen->invalid_inst_src)
return fn_ref;
- size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset;
- IrInstSrc **args = heap::c_allocator.allocate(arg_count);
- for (size_t i = 0; i < arg_count; i += 1) {
- AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset);
- IrInstSrc *arg = ir_gen_node(irb, arg_node, scope);
- if (arg == irb->codegen->invalid_inst_src)
- return arg;
- args[i] = arg;
- }
-
CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;
bool is_async_call_builtin = true;
- IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args,
- ret_ptr, modifier, is_async_call_builtin, bytes, result_loc);
+ AstNode *args_node = call_node->data.fn_call_expr.params.at(3);
+ if (args_node->type == NodeTypeContainerInitExpr) {
+ if (args_node->data.container_init_expr.kind == ContainerInitKindArray ||
+ args_node->data.container_init_expr.entries.length == 0)
+ {
+ size_t arg_count = args_node->data.container_init_expr.entries.length;
+ IrInstSrc **args = heap::c_allocator.allocate(arg_count);
+ for (size_t i = 0; i < arg_count; i += 1) {
+ AstNode *arg_node = args_node->data.container_init_expr.entries.at(i);
+ IrInstSrc *arg = ir_gen_node(irb, arg_node, scope);
+ if (arg == irb->codegen->invalid_inst_src)
+ return arg;
+ args[i] = arg;
+ }
+
+ IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args,
+ ret_ptr, modifier, is_async_call_builtin, bytes, result_loc);
+ return ir_lval_wrap(irb, scope, call, lval, result_loc);
+ } else {
+ exec_add_error_node(irb->codegen, irb->exec, args_node,
+ buf_sprintf("TODO: @asyncCall with anon struct literal"));
+ return irb->codegen->invalid_inst_src;
+ }
+ }
+ IrInstSrc *args = ir_gen_node(irb, args_node, scope);
+ if (args == irb->codegen->invalid_inst_src)
+ return args;
+
+ IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, bytes, ret_ptr, args, result_loc);
return ir_lval_wrap(irb, scope, call, lval, result_loc);
}
@@ -20236,7 +20277,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
// Fork a scope of the function with known values for the parameters.
Scope *parent_scope = fn_entry->fndef_scope->base.parent;
ZigFn *impl_fn = create_fn(ira->codegen, fn_proto_node);
- impl_fn->param_source_nodes = heap::c_allocator.allocate(new_fn_arg_count);
+
buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name);
impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn);
impl_fn->child_scope = &impl_fn->fndef_scope->base;
@@ -20719,40 +20760,101 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr,
modifier, stack, stack_src, false, args_ptr, args_len, nullptr, result_loc);
}
-static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCallExtra *instruction) {
- IrInstGen *args = instruction->args->child;
+static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_instr, CallModifier modifier,
+ IrInstSrc *pass1_fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstGen **args_ptr, size_t args_len, ResultLoc *result_loc)
+{
+ IrInstGen *fn_ref = pass1_fn_ref->child;
+ if (type_is_invalid(fn_ref->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (ir_should_inline(ira->old_irb.exec, source_instr->scope)) {
+ ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @asyncCall"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigFn *fn = nullptr;
+ if (instr_is_comptime(fn_ref)) {
+ if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
+ assert(fn_ref->value->special == ConstValSpecialStatic);
+ fn = fn_ref->value->data.x_bound_fn.fn;
+ } else {
+ fn = ir_resolve_fn(ira, fn_ref);
+ }
+ }
+
+ IrInstGen *ret_ptr_uncasted = nullptr;
+ if (ret_ptr != nullptr) {
+ ret_ptr_uncasted = ret_ptr->child;
+ if (type_is_invalid(ret_ptr_uncasted->value->type))
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;
+ IrInstGen *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack->child,
+ &new_stack->base, true, fn);
+ if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ IrInstGen *result = ir_analyze_async_call(ira, source_instr, fn, fn_type, fn_ref, args_ptr, args_len,
+ casted_new_stack, true, ret_ptr_uncasted, result_loc);
+ return ir_finish_anal(ira, result);
+}
+
+static bool ir_extract_tuple_call_args(IrAnalyze *ira, IrInst *source_instr, IrInstGen *args, IrInstGen ***args_ptr, size_t *args_len) {
ZigType *args_type = args->value->type;
if (type_is_invalid(args_type))
- return ira->codegen->invalid_inst_gen;
+ return false;
if (args_type->id != ZigTypeIdStruct) {
ir_add_error(ira, &args->base,
buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name)));
- return ira->codegen->invalid_inst_gen;
+ return false;
}
- IrInstGen **args_ptr = nullptr;
- size_t args_len = 0;
-
if (is_tuple(args_type)) {
- args_len = args_type->data.structure.src_field_count;
- args_ptr = heap::c_allocator.allocate(args_len);
- for (size_t i = 0; i < args_len; i += 1) {
+ *args_len = args_type->data.structure.src_field_count;
+ *args_ptr = heap::c_allocator.allocate(*args_len);
+ for (size_t i = 0; i < *args_len; i += 1) {
TypeStructField *arg_field = args_type->data.structure.fields[i];
- args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base.base, args, arg_field);
- if (type_is_invalid(args_ptr[i]->value->type))
- return ira->codegen->invalid_inst_gen;
+ (*args_ptr)[i] = ir_analyze_struct_value_field_value(ira, source_instr, args, arg_field);
+ if (type_is_invalid((*args_ptr)[i]->value->type))
+ return false;
}
} else {
ir_add_error(ira, &args->base, buf_sprintf("TODO: struct args"));
+ return false;
+ }
+ return true;
+}
+
+static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCallExtra *instruction) {
+ IrInstGen *args = instruction->args->child;
+ IrInstGen **args_ptr = nullptr;
+ size_t args_len = 0;
+ if (!ir_extract_tuple_call_args(ira, &instruction->base.base, args, &args_ptr, &args_len)) {
return ira->codegen->invalid_inst_gen;
}
+
IrInstGen *result = ir_analyze_call_extra(ira, &instruction->base.base, instruction->options,
instruction->fn_ref, args_ptr, args_len, instruction->result_loc);
heap::c_allocator.deallocate(args_ptr, args_len);
return result;
}
+static IrInstGen *ir_analyze_instruction_async_call_extra(IrAnalyze *ira, IrInstSrcAsyncCallExtra *instruction) {
+ IrInstGen *args = instruction->args->child;
+ IrInstGen **args_ptr = nullptr;
+ size_t args_len = 0;
+ if (!ir_extract_tuple_call_args(ira, &instruction->base.base, args, &args_ptr, &args_len)) {
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ IrInstGen *result = ir_analyze_async_call_extra(ira, &instruction->base.base, instruction->modifier,
+ instruction->fn_ref, instruction->ret_ptr, instruction->new_stack, args_ptr, args_len, instruction->result_loc);
+ heap::c_allocator.deallocate(args_ptr, args_len);
+ return result;
+}
+
static IrInstGen *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstSrcCallArgs *instruction) {
IrInstGen **args_ptr = heap::c_allocator.allocate(instruction->args_len);
for (size_t i = 0; i < instruction->args_len; i += 1) {
@@ -31101,6 +31203,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_call_args(ira, (IrInstSrcCallArgs *)instruction);
case IrInstSrcIdCallExtra:
return ir_analyze_instruction_call_extra(ira, (IrInstSrcCallExtra *)instruction);
+ case IrInstSrcIdAsyncCallExtra:
+ return ir_analyze_instruction_async_call_extra(ira, (IrInstSrcAsyncCallExtra *)instruction);
case IrInstSrcIdBr:
return ir_analyze_instruction_br(ira, (IrInstSrcBr *)instruction);
case IrInstSrcIdCondBr:
@@ -31610,6 +31714,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdDeclVar:
case IrInstSrcIdStorePtr:
case IrInstSrcIdCallExtra:
+ case IrInstSrcIdAsyncCallExtra:
case IrInstSrcIdCall:
case IrInstSrcIdCallArgs:
case IrInstSrcIdReturn:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 27bedff47f..0acde512f6 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -5,6 +5,7 @@
* See http://opensource.org/licenses/MIT
*/
+#include "all_types.hpp"
#include "analyze.hpp"
#include "ir.hpp"
#include "ir_print.hpp"
@@ -55,6 +56,36 @@ struct IrPrintGen {
static void ir_print_other_inst_src(IrPrintSrc *irp, IrInstSrc *inst);
static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst);
+static void ir_print_call_modifier(FILE *f, CallModifier modifier) {
+ switch (modifier) {
+ case CallModifierNone:
+ break;
+ case CallModifierNoSuspend:
+ fprintf(f, "nosuspend ");
+ break;
+ case CallModifierAsync:
+ fprintf(f, "async ");
+ break;
+ case CallModifierNeverTail:
+ fprintf(f, "notail ");
+ break;
+ case CallModifierNeverInline:
+ fprintf(f, "noinline ");
+ break;
+ case CallModifierAlwaysTail:
+ fprintf(f, "tail ");
+ break;
+ case CallModifierAlwaysInline:
+ fprintf(f, "inline ");
+ break;
+ case CallModifierCompileTime:
+ fprintf(f, "comptime ");
+ break;
+ case CallModifierBuiltin:
+ zig_unreachable();
+ }
+}
+
const char* ir_inst_src_type_str(IrInstSrcId id) {
switch (id) {
case IrInstSrcIdInvalid:
@@ -97,6 +128,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcVarPtr";
case IrInstSrcIdCallExtra:
return "SrcCallExtra";
+ case IrInstSrcIdAsyncCallExtra:
+ return "SrcAsyncCallExtra";
case IrInstSrcIdCall:
return "SrcCall";
case IrInstSrcIdCallArgs:
@@ -851,6 +884,23 @@ static void ir_print_call_extra(IrPrintSrc *irp, IrInstSrcCallExtra *instruction
ir_print_result_loc(irp, instruction->result_loc);
}
+static void ir_print_async_call_extra(IrPrintSrc *irp, IrInstSrcAsyncCallExtra *instruction) {
+ fprintf(irp->f, "modifier=");
+ ir_print_call_modifier(irp->f, instruction->modifier);
+ fprintf(irp->f, ", fn=");
+ ir_print_other_inst_src(irp, instruction->fn_ref);
+ if (instruction->ret_ptr != nullptr) {
+ fprintf(irp->f, ", ret_ptr=");
+ ir_print_other_inst_src(irp, instruction->ret_ptr);
+ }
+ fprintf(irp->f, ", new_stack=");
+ ir_print_other_inst_src(irp, instruction->new_stack);
+ fprintf(irp->f, ", args=");
+ ir_print_other_inst_src(irp, instruction->args);
+ fprintf(irp->f, ", result=");
+ ir_print_result_loc(irp, instruction->result_loc);
+}
+
static void ir_print_call_args(IrPrintSrc *irp, IrInstSrcCallArgs *instruction) {
fprintf(irp->f, "opts=");
ir_print_other_inst_src(irp, instruction->options);
@@ -868,33 +918,7 @@ static void ir_print_call_args(IrPrintSrc *irp, IrInstSrcCallArgs *instruction)
}
static void ir_print_call_src(IrPrintSrc *irp, IrInstSrcCall *call_instruction) {
- switch (call_instruction->modifier) {
- case CallModifierNone:
- break;
- case CallModifierNoSuspend:
- fprintf(irp->f, "nosuspend ");
- break;
- case CallModifierAsync:
- fprintf(irp->f, "async ");
- break;
- case CallModifierNeverTail:
- fprintf(irp->f, "notail ");
- break;
- case CallModifierNeverInline:
- fprintf(irp->f, "noinline ");
- break;
- case CallModifierAlwaysTail:
- fprintf(irp->f, "tail ");
- break;
- case CallModifierAlwaysInline:
- fprintf(irp->f, "inline ");
- break;
- case CallModifierCompileTime:
- fprintf(irp->f, "comptime ");
- break;
- case CallModifierBuiltin:
- zig_unreachable();
- }
+ ir_print_call_modifier(irp->f, call_instruction->modifier);
if (call_instruction->fn_entry) {
fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
} else {
@@ -913,33 +937,7 @@ static void ir_print_call_src(IrPrintSrc *irp, IrInstSrcCall *call_instruction)
}
static void ir_print_call_gen(IrPrintGen *irp, IrInstGenCall *call_instruction) {
- switch (call_instruction->modifier) {
- case CallModifierNone:
- break;
- case CallModifierNoSuspend:
- fprintf(irp->f, "nosuspend ");
- break;
- case CallModifierAsync:
- fprintf(irp->f, "async ");
- break;
- case CallModifierNeverTail:
- fprintf(irp->f, "notail ");
- break;
- case CallModifierNeverInline:
- fprintf(irp->f, "noinline ");
- break;
- case CallModifierAlwaysTail:
- fprintf(irp->f, "tail ");
- break;
- case CallModifierAlwaysInline:
- fprintf(irp->f, "inline ");
- break;
- case CallModifierCompileTime:
- fprintf(irp->f, "comptime ");
- break;
- case CallModifierBuiltin:
- zig_unreachable();
- }
+ ir_print_call_modifier(irp->f, call_instruction->modifier);
if (call_instruction->fn_entry) {
fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
} else {
@@ -2619,6 +2617,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdCallExtra:
ir_print_call_extra(irp, (IrInstSrcCallExtra *)instruction);
break;
+ case IrInstSrcIdAsyncCallExtra:
+ ir_print_async_call_extra(irp, (IrInstSrcAsyncCallExtra *)instruction);
+ break;
case IrInstSrcIdCall:
ir_print_call_src(irp, (IrInstSrcCall *)instruction);
break;
--
cgit v1.2.3
From eefcd044628ea080d8fe3346ae4d01e8ed4008e6 Mon Sep 17 00:00:00 2001
From: Alexandros Naskos
Date: Wed, 24 Jun 2020 16:56:24 +0300
Subject: Small fixes, fixed tests, added test for argument tuple type
---
src/ir.cpp | 15 ++++++++++-----
test/compile_errors.zig | 19 ++++++++++++++++---
test/stage1/behavior/async_fn.zig | 26 +++++++++++++-------------
3 files changed, 39 insertions(+), 21 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index b765ea09ff..5f44e5306b 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -6260,7 +6260,7 @@ static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *aw
if (args == irb->codegen->invalid_inst_src)
return args;
- IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, bytes, ret_ptr, args, result_loc);
+ IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc);
return ir_lval_wrap(irb, scope, call, lval, result_loc);
}
@@ -20277,7 +20277,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
// Fork a scope of the function with known values for the parameters.
Scope *parent_scope = fn_entry->fndef_scope->base.parent;
ZigFn *impl_fn = create_fn(ira->codegen, fn_proto_node);
-
+ impl_fn->param_source_nodes = heap::c_allocator.allocate(new_fn_arg_count);
buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name);
impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn);
impl_fn->child_scope = &impl_fn->fndef_scope->base;
@@ -20772,11 +20772,17 @@ static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_ins
return ira->codegen->invalid_inst_gen;
}
+ IrInstGen *first_arg_ptr = nullptr;
+ IrInst *first_arg_ptr_src = nullptr;
ZigFn *fn = nullptr;
if (instr_is_comptime(fn_ref)) {
if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
assert(fn_ref->value->special == ConstValSpecialStatic);
fn = fn_ref->value->data.x_bound_fn.fn;
+ first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
+ first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src;
+ if (type_is_invalid(first_arg_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
} else {
fn = ir_resolve_fn(ira, fn_ref);
}
@@ -20795,9 +20801,8 @@ static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_ins
if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
return ira->codegen->invalid_inst_gen;
- IrInstGen *result = ir_analyze_async_call(ira, source_instr, fn, fn_type, fn_ref, args_ptr, args_len,
- casted_new_stack, true, ret_ptr_uncasted, result_loc);
- return ir_finish_anal(ira, result);
+ return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr, first_arg_ptr_src,
+ modifier, casted_new_stack, &new_stack->base, true, args_ptr, args_len, ret_ptr_uncasted, result_loc);
}
static bool ir_extract_tuple_call_args(IrAnalyze *ira, IrInst *source_instr, IrInstGen *args, IrInstGen ***args_ptr, size_t *args_len) {
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index e8b7e610ee..90c970c842 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1144,13 +1144,26 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:2:15: error: @Type not available for 'TypeInfo.Struct'",
});
+ cases.add("wrong type for argument tuple to @asyncCall",
+ \\export fn entry1() void {
+ \\ var frame: @Frame(foo) = undefined;
+ \\ @asyncCall(&frame, {}, foo, {});
+ \\}
+ \\
+ \\fn foo() i32 {
+ \\ return 0;
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:3:33: error: expected tuple or struct, found 'void'",
+ });
+
cases.add("wrong type for result ptr to @asyncCall",
\\export fn entry() void {
\\ _ = async amain();
\\}
\\fn amain() i32 {
\\ var frame: @Frame(foo) = undefined;
- \\ return await @asyncCall(&frame, false, foo);
+ \\ return await @asyncCall(&frame, false, foo, .{});
\\}
\\fn foo() i32 {
\\ return 1234;
@@ -1291,7 +1304,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn entry() void {
\\ var ptr: fn () callconv(.Async) void = func;
\\ var bytes: [64]u8 = undefined;
- \\ _ = @asyncCall(&bytes, {}, ptr);
+ \\ _ = @asyncCall(&bytes, {}, ptr, .{});
\\}
\\fn func() callconv(.Async) void {}
, &[_][]const u8{
@@ -1467,7 +1480,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn entry() void {
\\ var ptr = afunc;
\\ var bytes: [100]u8 align(16) = undefined;
- \\ _ = @asyncCall(&bytes, {}, ptr);
+ \\ _ = @asyncCall(&bytes, {}, ptr, .{});
\\}
\\fn afunc() void { }
, &[_][]const u8{
diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig
index 30df7f64aa..4214ed84d2 100644
--- a/test/stage1/behavior/async_fn.zig
+++ b/test/stage1/behavior/async_fn.zig
@@ -282,7 +282,7 @@ test "async fn pointer in a struct field" {
};
var foo = Foo{ .bar = simpleAsyncFn2 };
var bytes: [64]u8 align(16) = undefined;
- const f = @asyncCall(&bytes, {}, foo.bar, &data);
+ const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
comptime expect(@TypeOf(f) == anyframe->void);
expect(data == 2);
resume f;
@@ -318,7 +318,7 @@ test "@asyncCall with return type" {
var foo = Foo{ .bar = Foo.middle };
var bytes: [150]u8 align(16) = undefined;
var aresult: i32 = 0;
- _ = @asyncCall(&bytes, &aresult, foo.bar);
+ _ = @asyncCall(&bytes, &aresult, foo.bar, .{});
expect(aresult == 0);
resume Foo.global_frame;
expect(aresult == 1234);
@@ -332,7 +332,7 @@ test "async fn with inferred error set" {
var frame: [1]@Frame(middle) = undefined;
var fn_ptr = middle;
var result: @TypeOf(fn_ptr).ReturnType.ErrorSet!void = undefined;
- _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr);
+ _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr, .{});
resume global_frame;
std.testing.expectError(error.Fail, result);
}
@@ -827,7 +827,7 @@ test "cast fn to async fn when it is inferred to be async" {
ptr = func;
var buf: [100]u8 align(16) = undefined;
var result: i32 = undefined;
- const f = @asyncCall(&buf, &result, ptr);
+ const f = @asyncCall(&buf, &result, ptr, .{});
_ = await f;
expect(result == 1234);
ok = true;
@@ -855,7 +855,7 @@ test "cast fn to async fn when it is inferred to be async, awaited directly" {
ptr = func;
var buf: [100]u8 align(16) = undefined;
var result: i32 = undefined;
- _ = await @asyncCall(&buf, &result, ptr);
+ _ = await @asyncCall(&buf, &result, ptr, .{});
expect(result == 1234);
ok = true;
}
@@ -951,7 +951,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
fn doTheTest() void {
var frame: [1]@Frame(middle) = undefined;
var result: @TypeOf(middle).ReturnType.ErrorSet!void = undefined;
- _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle);
+ _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle, .{});
resume global_frame;
std.testing.expectError(error.Fail, result);
}
@@ -982,7 +982,7 @@ test "@asyncCall with actual frame instead of byte buffer" {
};
var frame: @Frame(S.func) = undefined;
var result: i32 = undefined;
- const ptr = @asyncCall(&frame, &result, S.func);
+ const ptr = @asyncCall(&frame, &result, S.func, .{});
resume ptr;
expect(result == 1234);
}
@@ -1005,7 +1005,7 @@ test "@asyncCall using the result location inside the frame" {
};
var foo = Foo{ .bar = S.simple2 };
var bytes: [64]u8 align(16) = undefined;
- const f = @asyncCall(&bytes, {}, foo.bar, &data);
+ const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
comptime expect(@TypeOf(f) == anyframe->i32);
expect(data == 2);
resume f;
@@ -1042,7 +1042,7 @@ test "using @TypeOf on a generic function call" {
}
const F = @TypeOf(async amain(x - 1));
const frame = @intToPtr(*F, @ptrToInt(&buf));
- return await @asyncCall(frame, {}, amain, x - 1);
+ return await @asyncCall(frame, {}, amain, .{x - 1});
}
};
_ = async S.amain(@as(u32, 1));
@@ -1067,7 +1067,7 @@ test "recursive call of await @asyncCall with struct return type" {
}
const F = @TypeOf(async amain(x - 1));
const frame = @intToPtr(*F, @ptrToInt(&buf));
- return await @asyncCall(frame, {}, amain, x - 1);
+ return await @asyncCall(frame, {}, amain, .{x - 1});
}
const Foo = struct {
@@ -1078,7 +1078,7 @@ test "recursive call of await @asyncCall with struct return type" {
};
var res: S.Foo = undefined;
var frame: @TypeOf(async S.amain(@as(u32, 1))) = undefined;
- _ = @asyncCall(&frame, &res, S.amain, @as(u32, 1));
+ _ = @asyncCall(&frame, &res, S.amain, .{@as(u32, 1)});
resume S.global_frame;
expect(S.global_ok);
expect(res.x == 1);
@@ -1377,7 +1377,7 @@ test "async function call resolves target fn frame, comptime func" {
fn foo() anyerror!void {
const stack_size = 1000;
var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
- return await @asyncCall(&stack_frame, {}, bar);
+ return await @asyncCall(&stack_frame, {}, bar, .{});
}
fn bar() anyerror!void {
@@ -1400,7 +1400,7 @@ test "async function call resolves target fn frame, runtime func" {
const stack_size = 1000;
var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
var func: fn () callconv(.Async) anyerror!void = bar;
- return await @asyncCall(&stack_frame, {}, func);
+ return await @asyncCall(&stack_frame, {}, func, .{});
}
fn bar() anyerror!void {
--
cgit v1.2.3
From 2fde8249b72f22ddfa16793c245315f30c7f3ff8 Mon Sep 17 00:00:00 2001
From: Alexandros Naskos
Date: Wed, 24 Jun 2020 21:04:31 +0300
Subject: Fixed crash when resolving peer types of *[N:s]const T and [*:s]const
T
---
src/ir.cpp | 1 +
test/stage1/behavior.zig | 1 +
test/stage1/behavior/bugs/5413.zig | 6 ++++++
3 files changed, 8 insertions(+)
create mode 100644 test/stage1/behavior/bugs/5413.zig
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index 01c7936f75..3e2b75822e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -12603,6 +12603,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown)))
{
+ convert_to_const_slice = false;
prev_inst = cur_inst;
if (prev_type->data.pointer.is_const && !cur_type->data.pointer.is_const) {
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 8c567fa99f..a15f1f26b9 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -50,6 +50,7 @@ comptime {
_ = @import("behavior/bugs/4769_b.zig");
_ = @import("behavior/bugs/4769_c.zig");
_ = @import("behavior/bugs/4954.zig");
+ _ = @import("behavior/bugs/5413.zig");
_ = @import("behavior/bugs/5474.zig");
_ = @import("behavior/bugs/5487.zig");
_ = @import("behavior/bugs/394.zig");
diff --git a/test/stage1/behavior/bugs/5413.zig b/test/stage1/behavior/bugs/5413.zig
new file mode 100644
index 0000000000..5ef533a761
--- /dev/null
+++ b/test/stage1/behavior/bugs/5413.zig
@@ -0,0 +1,6 @@
+const expect = @import("std").testing.expect;
+
+test "Peer type resolution with string literals and unknown length u8 pointers" {
+ expect(@TypeOf("", "a", @as([*:0]const u8, "")) == [*:0]const u8);
+ expect(@TypeOf(@as([*:0]const u8, "baz"), "foo", "bar") == [*:0]const u8);
+}
--
cgit v1.2.3
From 78d8931647f207965ef98354db67fb880987fafe Mon Sep 17 00:00:00 2001
From: arbrk1
Date: Thu, 25 Jun 2020 06:58:50 +0300
Subject: Fix issue #5618 (#5685)
* fix issue #5618
* A test for the issue #5618 added.
Also inserted a comma in the neighboring test to make it more zigfmt-friendly.
---
src/ir.cpp | 1 +
test/compile_errors.zig | 12 +++++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index 3e2b75822e..20067b74d1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15452,6 +15452,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
if (is_pointery_and_elem_is_not_pointery(actual_type)) {
ZigType *dest_ptr_type = nullptr;
if (wanted_type->id == ZigTypeIdPointer &&
+ actual_type->id != ZigTypeIdOptional &&
wanted_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void)
{
dest_ptr_type = wanted_type;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index e8b7e610ee..79ecaee7c1 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -7571,6 +7571,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return -y;
\\}
, &[_][]const u8{
- "tmp.zig:3:12: error: negation of type 'u32'"
+ "tmp.zig:3:12: error: negation of type 'u32'",
+ });
+
+ cases.add("Issue #5618: coercion of ?*c_void to *c_void must fail.",
+ \\export fn foo() void {
+ \\ var u: ?*c_void = null;
+ \\ var v: *c_void = undefined;
+ \\ v = u;
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:4:9: error: expected type '*c_void', found '?*c_void'",
});
}
--
cgit v1.2.3
From 2e1bdd0d14f490a80bbed3ee0e0479a908715d33 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 9 Jul 2020 21:25:55 +0300
Subject: use correct cast function when doing `@floatCast` at comptime
Closes #5832
---
src/ir.cpp | 2 +-
test/stage1/behavior/cast.zig | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index a45455ad39..81b7f14f84 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -26718,7 +26718,7 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo
}
if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
- return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
+ return ir_analyze_widen_or_shorten(ira, &instruction->target->base, target, dest_type);
}
if (target->value->type->id != ZigTypeIdFloat) {
diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig
index 77cdacc307..4325b0b9e4 100644
--- a/test/stage1/behavior/cast.zig
+++ b/test/stage1/behavior/cast.zig
@@ -384,6 +384,19 @@ test "@intCast i32 to u7" {
expect(z == 0xff);
}
+test "@floatCast cast down" {
+ {
+ var double: f64 = 0.001534;
+ var single = @floatCast(f32, double);
+ expect(@TypeOf(single) == f32);
+ }
+ {
+ const double: f64 = 0.001534;
+ const single = @floatCast(f32, double);
+ expect(@TypeOf(single) == f32);
+ }
+}
+
test "implicit cast undefined to optional" {
expect(MakeType(void).getNull() == null);
expect(MakeType(void).getNonNull() != null);
--
cgit v1.2.3
From 02619edf413cd3b8b01a6a3514ecd257d7c08b6e Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 9 Jul 2020 23:24:21 -0700
Subject: Revert "use correct cast function when doing `@floatCast` at
comptime"
This reverts commit 2e1bdd0d14f490a80bbed3ee0e0479a908715d33.
Test failures
---
src/ir.cpp | 2 +-
test/stage1/behavior/cast.zig | 13 -------------
2 files changed, 1 insertion(+), 14 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index 81b7f14f84..a45455ad39 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -26718,7 +26718,7 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo
}
if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
- return ir_analyze_widen_or_shorten(ira, &instruction->target->base, target, dest_type);
+ return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
}
if (target->value->type->id != ZigTypeIdFloat) {
diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig
index 4325b0b9e4..77cdacc307 100644
--- a/test/stage1/behavior/cast.zig
+++ b/test/stage1/behavior/cast.zig
@@ -384,19 +384,6 @@ test "@intCast i32 to u7" {
expect(z == 0xff);
}
-test "@floatCast cast down" {
- {
- var double: f64 = 0.001534;
- var single = @floatCast(f32, double);
- expect(@TypeOf(single) == f32);
- }
- {
- const double: f64 = 0.001534;
- const single = @floatCast(f32, double);
- expect(@TypeOf(single) == f32);
- }
-}
-
test "implicit cast undefined to optional" {
expect(MakeType(void).getNull() == null);
expect(MakeType(void).getNonNull() != null);
--
cgit v1.2.3
From 2e037fd827487ce94ae0beb313a1f0536085d61e Mon Sep 17 00:00:00 2001
From: Vexu
Date: Fri, 10 Jul 2020 17:30:50 +0300
Subject: use correct cast function when doing `@floatCast` at comptime
---
src/ir.cpp | 20 +++++++++++++-------
test/compile_errors.zig | 32 ++++++++++++++++++--------------
test/stage1/behavior/cast.zig | 13 +++++++++++++
3 files changed, 44 insertions(+), 21 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index a45455ad39..ca0fd47c49 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -13020,7 +13020,11 @@ static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGe
{
if (instr_is_comptime(value) || !type_has_bits(ira->codegen, wanted_type)) {
IrInstGen *result = ir_const(ira, source_instr, wanted_type);
- if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, value->value, value->value->type,
+ ZigValue *val = ir_resolve_const(ira, value, UndefBad);
+ if (val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, val, val->type,
result->value, wanted_type))
{
return ira->codegen->invalid_inst_gen;
@@ -26680,6 +26684,10 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa
}
if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeInt) {
+ ZigValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
}
@@ -26718,13 +26726,11 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo
}
if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
- return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
- }
+ ZigValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (val == nullptr)
+ return ira->codegen->invalid_inst_gen;
- if (target->value->type->id != ZigTypeIdFloat) {
- ir_add_error(ira, &instruction->target->base, buf_sprintf("expected float type, found '%s'",
- buf_ptr(&target->value->type->name)));
- return ira->codegen->invalid_inst_gen;
+ return ir_analyze_widen_or_shorten(ira, &instruction->target->base, target, dest_type);
}
return ir_analyze_widen_or_shorten(ira, &instruction->base.base, target, dest_type);
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 611094c050..df2e759bf1 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,22 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.addTest("int/float conversion to comptime_int/float",
+ \\export fn foo() void {
+ \\ var a: f32 = 2;
+ \\ _ = @floatToInt(comptime_int, a);
+ \\}
+ \\export fn bar() void {
+ \\ var a: u32 = 2;
+ \\ _ = @intToFloat(comptime_float, a);
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:3:35: error: unable to evaluate constant expression",
+ "tmp.zig:3:9: note: referenced here",
+ "tmp.zig:7:37: error: unable to evaluate constant expression",
+ "tmp.zig:7:9: note: referenced here",
+ });
+
cases.add("extern variable has no type",
\\extern var foo;
\\pub export fn entry() void {
@@ -90,19 +106,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var a: u32 = 2;
\\ _ = @floatToInt(u32, a);
\\}
- \\export fn qux() void {
- \\ var a: u32 = 2;
- \\ _ = @intCast(comptime_int, a);
- \\}
, &[_][]const u8{
- "tmp.zig:3:32: error: expected type 'comptime_int', found 'u32'",
+ "tmp.zig:3:32: error: unable to evaluate constant expression",
"tmp.zig:3:9: note: referenced here",
"tmp.zig:7:21: error: expected float type, found 'u32'",
"tmp.zig:7:9: note: referenced here",
"tmp.zig:11:26: error: expected float type, found 'u32'",
"tmp.zig:11:9: note: referenced here",
- "tmp.zig:15:32: error: expected type 'comptime_int', found 'u32'",
- "tmp.zig:15:9: note: referenced here",
});
cases.addTest("invalid float casts",
@@ -118,19 +128,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var a: f32 = 2;
\\ _ = @intToFloat(f32, a);
\\}
- \\export fn qux() void {
- \\ var a: f32 = 2;
- \\ _ = @floatCast(comptime_float, a);
- \\}
, &[_][]const u8{
- "tmp.zig:3:36: error: expected type 'comptime_float', found 'f32'",
+ "tmp.zig:3:36: error: unable to evaluate constant expression",
"tmp.zig:3:9: note: referenced here",
"tmp.zig:7:21: error: expected integer type, found 'f32'",
"tmp.zig:7:9: note: referenced here",
"tmp.zig:11:26: error: expected int type, found 'f32'",
"tmp.zig:11:9: note: referenced here",
- "tmp.zig:15:36: error: expected type 'comptime_float', found 'f32'",
- "tmp.zig:15:9: note: referenced here",
});
cases.addTest("invalid assignments",
diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig
index 77cdacc307..4b678cd2db 100644
--- a/test/stage1/behavior/cast.zig
+++ b/test/stage1/behavior/cast.zig
@@ -384,6 +384,19 @@ test "@intCast i32 to u7" {
expect(z == 0xff);
}
+test "@floatCast cast down" {
+ {
+ var double: f64 = 0.001534;
+ var single = @floatCast(f32, double);
+ expect(single == 0.001534);
+ }
+ {
+ const double: f64 = 0.001534;
+ const single = @floatCast(f32, double);
+ expect(single == 0.001534);
+ }
+}
+
test "implicit cast undefined to optional" {
expect(MakeType(void).getNull() == null);
expect(MakeType(void).getNonNull() != null);
--
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/ir.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 dff1ac1089dd8a7cae5c167bdb4e6269c9b84bb6 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Sat, 11 Jul 2020 12:08:29 +0300
Subject: check for invalid sentinel when creating pointer with `@Type`
---
src/ir.cpp | 7 ++++++-
test/compile_errors.zig | 16 ++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index 6447db8c71..dc380b4389 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25915,6 +25915,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
{
return ira->codegen->invalid_inst_gen->value->type;
}
+ if (sentinel != nullptr && (size_enum_index == BuiltinPtrSizeOne || size_enum_index == BuiltinPtrSizeC)) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("sentinels are only allowed on slices and unknown-length pointers"));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);
if (bi == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
@@ -25948,7 +25953,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
0, // host_int_bytes
is_allowzero,
VECTOR_INDEX_NONE, nullptr, sentinel);
- if (size_enum_index != 2)
+ if (size_enum_index != BuiltinPtrSizeSlice)
return ptr_type;
return get_slice_type(ira->codegen, ptr_type);
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index fb4428fbc6..5de56f8ca7 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,22 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.addTest("invalid pointer with @Type",
+ \\export fn entry() void {
+ \\ _ = @Type(.{ .Pointer = .{
+ \\ .size = .One,
+ \\ .is_const = false,
+ \\ .is_volatile = false,
+ \\ .alignment = 1,
+ \\ .child = u8,
+ \\ .is_allowzero = false,
+ \\ .sentinel = 0,
+ \\ }});
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:2:16: error: sentinels are only allowed on slices and unknown-length pointers",
+ });
+
cases.addTest("int/float conversion to comptime_int/float",
\\export fn foo() void {
\\ var a: f32 = 2;
--
cgit v1.2.3
From 4696cd3e09c4e33519dbb53a41c32bbdfd97f6f6 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 14 Jul 2020 14:38:40 -0700
Subject: fix ability to call methods on enums with pointer-to-self
closes #3218
---
src/ir.cpp | 6 ++----
test/stage1/behavior/enum.zig | 19 +++++++++++++++++++
test/stage1/behavior/union.zig | 21 +++++++++++++++++++++
3 files changed, 42 insertions(+), 4 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index dc380b4389..0dd8f4e86a 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -20182,7 +20182,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
}
IrInstGen *first_arg;
- if (!first_arg_known_bare && handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type)) {
+ if (!first_arg_known_bare) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
@@ -20522,9 +20522,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
return ira->codegen->invalid_inst_gen;
IrInstGen *first_arg;
- if (param_type->id == ZigTypeIdPointer &&
- handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type))
- {
+ if (param_type->id == ZigTypeIdPointer) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig
index 765828f5ce..b9bb1db533 100644
--- a/test/stage1/behavior/enum.zig
+++ b/test/stage1/behavior/enum.zig
@@ -1140,3 +1140,22 @@ test "tagName on enum literals" {
expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
comptime expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
}
+
+test "method call on an enum" {
+ const S = struct {
+ const E = enum {
+ one,
+ two,
+
+ fn method(self: *E) bool {
+ return self.* == .two;
+ }
+ };
+ fn doTheTest() void {
+ var e = E.two;
+ expect(e.method());
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig
index da898347b9..cf3412eb5b 100644
--- a/test/stage1/behavior/union.zig
+++ b/test/stage1/behavior/union.zig
@@ -669,3 +669,24 @@ test "cast from anonymous struct to union" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "method call on an empty union" {
+ const S = struct {
+ const MyUnion = union(Tag) {
+ pub const Tag = enum { X1, X2 };
+ X1: [0]u8,
+ X2: [0]u8,
+
+ pub fn useIt(self: *@This()) bool {
+ return true;
+ }
+ };
+
+ fn doTheTest() void {
+ var u = MyUnion{ .X1 = [0]u8{} };
+ expect(u.useIt());
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
--
cgit v1.2.3
From a7c3cec65f1639195e787b98900c3f126953f880 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 14 Jul 2020 15:29:07 -0700
Subject: follow up from previous commit for generic methods
---
src/ir.cpp | 2 +-
test/stage1/behavior/enum.zig | 5 +++++
2 files changed, 6 insertions(+), 1 deletion(-)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index 0dd8f4e86a..e162125fb4 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -20317,7 +20317,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
}
IrInstGen *first_arg;
- if (!first_arg_known_bare && handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type)) {
+ if (!first_arg_known_bare) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig
index b9bb1db533..f569264520 100644
--- a/test/stage1/behavior/enum.zig
+++ b/test/stage1/behavior/enum.zig
@@ -1150,10 +1150,15 @@ test "method call on an enum" {
fn method(self: *E) bool {
return self.* == .two;
}
+
+ fn generic_method(self: *E, foo: anytype) bool {
+ return self.* == .two and foo == bool;
+ }
};
fn doTheTest() void {
var e = E.two;
expect(e.method());
+ expect(e.generic_method(bool));
}
};
S.doTheTest();
--
cgit v1.2.3
From a1e78d0b0631885b95dfa80ab617818d1fd61277 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 16 Jul 2020 23:35:31 +0300
Subject: add is_tuple field to struct typeinfo
part of #4335
---
lib/std/builtin.zig | 1 +
lib/std/mem.zig | 5 ++---
src/ir.cpp | 8 +++++++-
test/stage1/behavior/type_info.zig | 7 ++++++-
4 files changed, 16 insertions(+), 5 deletions(-)
(limited to 'src/ir.cpp')
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 5eafc4e409..499011eab9 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -246,6 +246,7 @@ pub const TypeInfo = union(enum) {
layout: ContainerLayout,
fields: []const StructField,
decls: []const Declaration,
+ is_tuple: bool,
};
/// This data structure is used by the Zig language code generation and
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index f4489a4867..ac7bde47c1 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -709,8 +709,7 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
.Struct => |init_info| {
var value = std.mem.zeroes(T);
- // typeInfo won't tell us if this is a tuple
- if (comptime eql(u8, init_info.fields[0].name, "0")) {
+ if (init_info.is_tuple) {
inline for (init_info.fields) |field, i| {
@field(value, struct_info.fields[i].name) = @field(init, field.name);
}
@@ -785,7 +784,7 @@ test "zeroInit" {
a: u8,
};
- const c = zeroInit(Color, .{255, 255});
+ const c = zeroInit(Color, .{ 255, 255 });
testing.expectEqual(Color{
.r = 255,
.g = 255,
diff --git a/src/ir.cpp b/src/ir.cpp
index e162125fb4..d027badac1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25546,7 +25546,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
result->special = ConstValSpecialStatic;
result->type = ir_type_info_get_type(ira, "Struct", nullptr);
- ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 3);
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
result->data.x_struct.fields = fields;
// layout: ContainerLayout
@@ -25627,6 +25627,12 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
return err;
}
+ // is_tuple: bool
+ ensure_field_index(result->type, "is_tuple", 3);
+ fields[3]->special = ConstValSpecialStatic;
+ fields[3]->type = ira->codegen->builtin_types.entry_bool;
+ fields[3]->data.x_bool = is_tuple(type_entry);
+
break;
}
case ZigTypeIdFn:
diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig
index d4c8cec977..a79b3a1554 100644
--- a/test/stage1/behavior/type_info.zig
+++ b/test/stage1/behavior/type_info.zig
@@ -280,7 +280,7 @@ fn testFunction() void {
expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
}
-extern fn foo(a: usize, b: bool, args: ...) usize;
+extern fn foo(a: usize, b: bool, ...) usize;
test "typeInfo with comptime parameter in struct fn def" {
const S = struct {
@@ -425,3 +425,8 @@ test "Declarations are returned in declaration order" {
expect(std.mem.eql(u8, d[3].name, "d"));
expect(std.mem.eql(u8, d[4].name, "e"));
}
+
+test "Struct.is_tuple" {
+ expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
+ expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
+}
--
cgit v1.2.3
From 78962eeeda07d613ebdfd239082268a6702c19db Mon Sep 17 00:00:00 2001
From: Vexu
Date: Sat, 18 Jul 2020 10:22:15 +0300
Subject: fix floatCast type check regression
Closes #5900
---
src/ir.cpp | 6 ++++++
test/compile_errors.zig | 12 ++++++++++++
2 files changed, 18 insertions(+)
(limited to 'src/ir.cpp')
diff --git a/src/ir.cpp b/src/ir.cpp
index d027badac1..88e111ccb5 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -26739,6 +26739,12 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo
}
}
+ if (target->value->type->id != ZigTypeIdFloat) {
+ ir_add_error(ira, &instruction->target->base, buf_sprintf("expected float type, found '%s'",
+ buf_ptr(&target->value->type->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
ZigValue *val = ir_resolve_const(ira, target, UndefBad);
if (val == nullptr)
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 5de56f8ca7..a1a261f887 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -122,6 +122,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var a: u32 = 2;
\\ _ = @floatToInt(u32, a);
\\}
+ \\export fn qux() void {
+ \\ var a: f32 = 2;
+ \\ _ = @intCast(u32, a);
+ \\}
, &[_][]const u8{
"tmp.zig:3:32: error: unable to evaluate constant expression",
"tmp.zig:3:9: note: referenced here",
@@ -129,6 +133,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:7:9: note: referenced here",
"tmp.zig:11:26: error: expected float type, found 'u32'",
"tmp.zig:11:9: note: referenced here",
+ "tmp.zig:15:23: error: expected integer type, found 'f32'",
+ "tmp.zig:15:9: note: referenced here",
});
cases.addTest("invalid float casts",
@@ -144,6 +150,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var a: f32 = 2;
\\ _ = @intToFloat(f32, a);
\\}
+ \\export fn qux() void {
+ \\ var a: u32 = 2;
+ \\ _ = @floatCast(f32, a);
+ \\}
, &[_][]const u8{
"tmp.zig:3:36: error: unable to evaluate constant expression",
"tmp.zig:3:9: note: referenced here",
@@ -151,6 +161,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:7:9: note: referenced here",
"tmp.zig:11:26: error: expected int type, found 'f32'",
"tmp.zig:11:9: note: referenced here",
+ "tmp.zig:15:25: error: expected float type, found 'u32'",
+ "tmp.zig:15:9: note: referenced here",
});
cases.addTest("invalid assignments",
--
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/ir.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