mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
commit
7a881435ed
@ -4265,10 +4265,13 @@ fn structDeclInner(
|
||||
// are in scope, so that field types, alignments, and default value expressions
|
||||
// can refer to decls within the struct itself.
|
||||
astgen.advanceSourceCursorToNode(node);
|
||||
// If `node == 0` then this is the root struct and all the declarations should
|
||||
// be relative to the beginning of the file.
|
||||
const decl_line = if (node == 0) 0 else astgen.source_line;
|
||||
var block_scope: GenZir = .{
|
||||
.parent = &namespace.base,
|
||||
.decl_node_index = node,
|
||||
.decl_line = astgen.source_line,
|
||||
.decl_line = decl_line,
|
||||
.astgen = astgen,
|
||||
.force_comptime = true,
|
||||
.in_defer = false,
|
||||
@ -11756,7 +11759,6 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
|
||||
}
|
||||
}
|
||||
|
||||
// const index_name = try astgen.identAsString(index_token);
|
||||
var s = namespace.parent;
|
||||
while (true) switch (s.tag) {
|
||||
.local_val => {
|
||||
|
||||
48
src/Sema.zig
48
src/Sema.zig
@ -78,6 +78,9 @@ post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
|
||||
err: ?*Module.ErrorMsg = null,
|
||||
/// True when analyzing a generic instantiation. Used to suppress some errors.
|
||||
is_generic_instantiation: bool = false,
|
||||
/// Set to true when analyzing a func type instruction so that nested generic
|
||||
/// function types will emit generic poison instead of a partial type.
|
||||
no_partial_func_ty: bool = false,
|
||||
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
@ -4068,6 +4071,19 @@ fn zirValidateArrayInit(
|
||||
|
||||
// Determine whether the value stored to this pointer is comptime-known.
|
||||
|
||||
if (array_ty.isTuple()) {
|
||||
if (array_ty.structFieldValueComptime(i)) |opv| {
|
||||
element_vals[i] = opv;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Array has one possible value, so value is always comptime-known
|
||||
if (opt_opv) |opv| {
|
||||
element_vals[i] = opv;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
|
||||
const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;
|
||||
// Find the block index of the elem_ptr so that we can look at the next
|
||||
@ -4084,19 +4100,6 @@ fn zirValidateArrayInit(
|
||||
}
|
||||
first_block_index = @minimum(first_block_index, block_index);
|
||||
|
||||
if (array_ty.isTuple()) {
|
||||
if (array_ty.structFieldValueComptime(i)) |opv| {
|
||||
element_vals[i] = opv;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Array has one possible value, so value is always comptime-known
|
||||
if (opt_opv) |opv| {
|
||||
element_vals[i] = opv;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If the next instructon is a store with a comptime operand, this element
|
||||
// is comptime.
|
||||
const next_air_inst = block.instructions.items[block_index + 1];
|
||||
@ -5938,10 +5941,9 @@ fn analyzeCall(
|
||||
undefined,
|
||||
) catch |err| switch (err) {
|
||||
error.NeededSourceLocation => {
|
||||
sema.inst_map.clearRetainingCapacity();
|
||||
_ = sema.inst_map.remove(inst);
|
||||
const decl = sema.mod.declPtr(block.src_decl);
|
||||
child_block.src_decl = block.src_decl;
|
||||
arg_i = 0;
|
||||
try sema.analyzeInlineCallArg(
|
||||
block,
|
||||
&child_block,
|
||||
@ -7917,6 +7919,7 @@ fn funcCommon(
|
||||
if (cc_workaround == .Inline and is_noinline) {
|
||||
return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
|
||||
}
|
||||
if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
|
||||
|
||||
break :fn_ty try Type.Tag.function.create(sema.arena, .{
|
||||
.param_types = param_types,
|
||||
@ -8097,25 +8100,19 @@ fn zirParam(
|
||||
// Make sure any nested param instructions don't clobber our work.
|
||||
const prev_params = block.params;
|
||||
const prev_preallocated_new_func = sema.preallocated_new_func;
|
||||
const prev_no_partial_func_type = sema.no_partial_func_ty;
|
||||
block.params = .{};
|
||||
sema.preallocated_new_func = null;
|
||||
sema.no_partial_func_ty = true;
|
||||
defer {
|
||||
block.params.deinit(sema.gpa);
|
||||
block.params = prev_params;
|
||||
sema.preallocated_new_func = prev_preallocated_new_func;
|
||||
sema.no_partial_func_ty = prev_no_partial_func_type;
|
||||
}
|
||||
|
||||
if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
|
||||
if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {
|
||||
if (param_ty.zigTypeTag() == .Fn and param_ty.fnInfo().is_generic) {
|
||||
// zirFunc will not emit error.GenericPoison to build a
|
||||
// partial type for generic functions but we still need to
|
||||
// detect if a function parameter is a generic function
|
||||
// to force the parent function to also be generic.
|
||||
if (!sema.inst_map.contains(inst)) {
|
||||
break :err error.GenericPoison;
|
||||
}
|
||||
}
|
||||
break :param_ty param_ty;
|
||||
} else |err| break :err err;
|
||||
} else |err| break :err err;
|
||||
@ -26140,11 +26137,12 @@ fn analyzeSlice(
|
||||
var array_ty = ptr_ptr_child_ty;
|
||||
var slice_ty = ptr_ptr_ty;
|
||||
var ptr_or_slice = ptr_ptr;
|
||||
var elem_ty = ptr_ptr_child_ty.childType();
|
||||
var elem_ty: Type = undefined;
|
||||
var ptr_sentinel: ?Value = null;
|
||||
switch (ptr_ptr_child_ty.zigTypeTag()) {
|
||||
.Array => {
|
||||
ptr_sentinel = ptr_ptr_child_ty.sentinel();
|
||||
elem_ty = ptr_ptr_child_ty.childType();
|
||||
},
|
||||
.Pointer => switch (ptr_ptr_child_ty.ptrSize()) {
|
||||
.One => {
|
||||
|
||||
@ -2689,6 +2689,12 @@ pub const Value = extern union {
|
||||
// to have only one possible value itself.
|
||||
.the_only_possible_value => return val,
|
||||
|
||||
// pointer to integer casted to pointer of array
|
||||
.int_u64, .int_i64 => {
|
||||
assert(index == 0);
|
||||
return val;
|
||||
},
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,3 +342,18 @@ test "generic instantiation of tagged union with only one field" {
|
||||
try expect(S.foo(.{ .s = "a" }) == 1);
|
||||
try expect(S.foo(.{ .s = "ab" }) == 2);
|
||||
}
|
||||
|
||||
test "nested generic function" {
|
||||
const S = struct {
|
||||
fn foo(comptime T: type, callback: *const fn (user_data: T) anyerror!void, data: T) anyerror!void {
|
||||
try callback(data);
|
||||
}
|
||||
fn bar(a: u32) anyerror!void {
|
||||
try expect(a == 123);
|
||||
}
|
||||
|
||||
fn g(_: *const fn (anytype) void) void {}
|
||||
};
|
||||
try expect(@typeInfo(@TypeOf(S.g)).Fn.is_generic);
|
||||
try S.foo(u32, S.bar, 123);
|
||||
}
|
||||
|
||||
@ -290,3 +290,14 @@ test "coerce tuple to tuple" {
|
||||
};
|
||||
try S.foo(.{123});
|
||||
}
|
||||
|
||||
test "tuple type with void field" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
const T = std.meta.Tuple(&[_]type{void});
|
||||
const x = T{{}};
|
||||
try expect(@TypeOf(x[0]) == void);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
fn f(_: anytype) void {}
|
||||
fn g(h: *const fn (anytype) void) void {
|
||||
const T = *const fn (anytype) void;
|
||||
fn g(h: T) void {
|
||||
h({});
|
||||
}
|
||||
pub export fn entry() void {
|
||||
@ -19,5 +20,5 @@ pub export fn entry1() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:6: error: parameter of type '*const fn(anytype) void' must be declared comptime
|
||||
// :9:34: error: parameter of type 'comptime_int' must be declared comptime
|
||||
// :3:6: error: parameter of type '*const fn(anytype) void' must be declared comptime
|
||||
// :10:34: error: parameter of type 'comptime_int' must be declared comptime
|
||||
|
||||
14
test/cases/compile_errors/error_in_typeof_param.zig
Normal file
14
test/cases/compile_errors/error_in_typeof_param.zig
Normal file
@ -0,0 +1,14 @@
|
||||
fn getSize() usize {
|
||||
return 2;
|
||||
}
|
||||
pub fn expectEqual(expected: anytype, _: @TypeOf(expected)) !void {}
|
||||
pub export fn entry() void {
|
||||
try expectEqual(2, getSize());
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:31: error: unable to resolve comptime value
|
||||
// :6:31: note: argument to parameter with comptime only type must be comptime known
|
||||
9
test/cases/compile_errors/slice_of_non_array_type.zig
Normal file
9
test/cases/compile_errors/slice_of_non_array_type.zig
Normal file
@ -0,0 +1,9 @@
|
||||
comptime {
|
||||
_ = 1[0..];
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:10: error: slice of non-array type 'comptime_int'
|
||||
Loading…
x
Reference in New Issue
Block a user