aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-23 23:28:05 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-23 23:28:05 -0700
commit2af69710a7b1513f3540ae0e1178cb5f3948204d (patch)
tree9f8aa5fd7d80ec976a5355348e7b3a6347caf1b5 /src
parentaca42c62598523b92de7a51d3d84f2f2e5146536 (diff)
downloadzig-2af69710a7b1513f3540ae0e1178cb5f3948204d.tar.gz
zig-2af69710a7b1513f3540ae0e1178cb5f3948204d.zip
stage2: fix some generics issues
* std.meta: correct use of `default_value` in reification. stage1 accepted a wrong type for `null`. * Sema: after instantiating a generic function, if the return type ends up being a comptime-known type, then we return an error, undoing the generic function instantiation, and making a comptime function call instead. - We also needed to clean up the dependency graph in this case. * Sema: reified enums set tag_ty_inferred to false since an integer tag type is provided. This is a limitation of the `@Type` builtin which will be addressed with #10710. * Sema: fix resolveInferredErrorSet incorrectly calling ensureFuncBodyAnalyzed on generic functions.
Diffstat (limited to 'src')
-rw-r--r--src/Module.zig4
-rw-r--r--src/Sema.zig57
2 files changed, 46 insertions, 15 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 79d6343949..0666936f1f 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -781,11 +781,11 @@ pub const Decl = struct {
return &decl_plus_emit_h.emit_h;
}
- fn removeDependant(decl: *Decl, other: *Decl) void {
+ pub fn removeDependant(decl: *Decl, other: *Decl) void {
assert(decl.dependants.swapRemove(other));
}
- fn removeDependency(decl: *Decl, other: *Decl) void {
+ pub fn removeDependency(decl: *Decl, other: *Decl) void {
assert(decl.dependencies.swapRemove(other));
}
diff --git a/src/Sema.zig b/src/Sema.zig
index d8cc908ae8..277e4a6ba6 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -4688,7 +4688,7 @@ fn analyzeCall(
const gpa = sema.gpa;
- const is_comptime_call = block.is_comptime or modifier == .compile_time or
+ var is_comptime_call = block.is_comptime or modifier == .compile_time or
try sema.typeRequiresComptime(block, func_src, func_ty_info.return_type);
var is_inline_call = is_comptime_call or modifier == .always_inline or
func_ty_info.cc == .Inline;
@@ -4706,7 +4706,13 @@ fn analyzeCall(
)) |some| {
return some;
} else |err| switch (err) {
- error.GenericPoison => is_inline_call = true,
+ error.GenericPoison => {
+ is_inline_call = true;
+ },
+ error.ComptimeReturn => {
+ is_inline_call = true;
+ is_comptime_call = true;
+ },
else => |e| return e,
}
}
@@ -5149,7 +5155,13 @@ fn instantiateGenericCall(
// of each of its instantiations.
assert(new_decl.dependencies.keys().len == 0);
try mod.declareDeclDependency(new_decl, module_fn.owner_decl);
- errdefer assert(module_fn.owner_decl.dependants.orderedRemove(new_decl));
+ // Resolving the new function type below will possibly declare more decl dependencies
+ // and so we remove them all here in case of error.
+ errdefer {
+ for (new_decl.dependencies.keys()) |dep| {
+ dep.removeDependant(new_decl);
+ }
+ }
var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
errdefer new_decl_arena.deinit();
@@ -5285,8 +5297,17 @@ fn instantiateGenericCall(
// Populate the Decl ty/val with the function and its type.
new_decl.ty = try child_sema.typeOf(new_func_inst).copy(new_decl_arena_allocator);
- // If the call evaluated to a generic type return errror and call inline.
- if (new_decl.ty.fnInfo().is_generic) return error.GenericPoison;
+ // If the call evaluated to a return type that requires comptime, never mind
+ // our generic instantiation. Instead we need to perform a comptime call.
+ const new_fn_info = new_decl.ty.fnInfo();
+ if (try sema.typeRequiresComptime(block, call_src, new_fn_info.return_type)) {
+ return error.ComptimeReturn;
+ }
+ // Similarly, if the call evaluated to a generic type we need to instead
+ // call it inline.
+ if (new_fn_info.is_generic or new_fn_info.cc == .Inline) {
+ return error.GenericPoison;
+ }
new_decl.val = try Value.Tag.function.create(new_decl_arena_allocator, new_func);
new_decl.has_tv = true;
@@ -12978,10 +12999,14 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
new_decl.owns_tv = true;
errdefer mod.abortAnonDecl(new_decl);
+ // Enum tag type
+ var buffer: Value.ToTypeBuffer = undefined;
+ const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator);
+
enum_obj.* = .{
.owner_decl = new_decl,
- .tag_ty = Type.@"null",
- .tag_ty_inferred = true,
+ .tag_ty = int_tag_ty,
+ .tag_ty_inferred = false,
.fields = .{},
.values = .{},
.node_offset = src.node_offset,
@@ -12992,10 +13017,6 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
},
};
- // Enum tag type
- var buffer: Value.ToTypeBuffer = undefined;
- enum_obj.tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator);
-
// Fields
const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(target));
if (fields_len > 0) {
@@ -21111,8 +21132,18 @@ fn resolveInferredErrorSet(
return sema.fail(block, src, "unable to resolve inferred error set", .{});
}
- // To ensure that all dependencies are properly added to the set.
- try sema.ensureFuncBodyAnalyzed(ies.func);
+ // In order to ensure that all dependencies are properly added to the set, we
+ // need to ensure the function body is analyzed of the inferred error set.
+ // However, in the case of comptime/inline function calls with inferred error sets,
+ // each call gets a new InferredErrorSet object, which points to the same
+ // `*Module.Fn`. Not only is the function not relevant to the inferred error set
+ // in this case, it may be a generic function which would cause an assertion failure
+ // if we called `ensureFuncBodyAnalyzed` on it here.
+ if (ies.func.owner_decl.ty.fnInfo().return_type.errorUnionSet().castTag(.error_set_inferred).?.data == ies) {
+ // In this case we are dealing with the actual InferredErrorSet object that
+ // corresponds to the function, not one created to track an inline/comptime call.
+ try sema.ensureFuncBodyAnalyzed(ies.func);
+ }
ies.is_resolved = true;