diff options
| -rw-r--r-- | src/Module.zig | 10 | ||||
| -rw-r--r-- | src/Sema.zig | 11 | ||||
| -rw-r--r-- | test/cases/compile_errors/closure_get_depends_on_failed_decl.zig | 26 | ||||
| -rw-r--r-- | test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig | 24 |
4 files changed, 70 insertions, 1 deletions
diff --git a/src/Module.zig b/src/Module.zig index 3ae6c48edd..ea89225537 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -345,6 +345,15 @@ pub const CaptureScope = struct { /// During sema, this map is backed by the gpa. Once sema completes, /// it is reallocated using the value_arena. captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, TypedValue) = .{}, + + pub fn failed(noalias self: *const @This()) bool { + return self.captures.available == 0 and self.captures.size == std.math.maxInt(u32); + } + + pub fn fail(noalias self: *@This()) void { + self.captures.available = 0; + self.captures.size = std.math.maxInt(u32); + } }; pub const WipCaptureScope = struct { @@ -383,6 +392,7 @@ pub const WipCaptureScope = struct { pub fn deinit(noalias self: *@This()) void { if (!self.finalized) { self.scope.captures.deinit(self.gpa); + self.scope.fail(); } self.* = undefined; } diff --git a/src/Sema.zig b/src/Sema.zig index 8d25a7c93e..15e891ef87 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5956,7 +5956,6 @@ fn analyzeCall( error.NeededSourceLocation => { _ = sema.inst_map.remove(inst); const decl = sema.mod.declPtr(block.src_decl); - child_block.src_decl = block.src_decl; try sema.analyzeInlineCallArg( block, &child_block, @@ -13740,6 +13739,16 @@ fn zirClosureGet( const tv = while (true) { // Note: We don't need to add a dependency here, because // decls always depend on their lexical parents. + + // Fail this decl if a scope it depended on failed. + if (scope.failed()) { + if (sema.owner_func) |owner_func| { + owner_func.state = .dependency_failure; + } else { + sema.owner_decl.analysis = .dependency_failure; + } + return error.AnalysisFail; + } if (scope.captures.getPtr(inst_data.inst)) |tv| { break tv; } diff --git a/test/cases/compile_errors/closure_get_depends_on_failed_decl.zig b/test/cases/compile_errors/closure_get_depends_on_failed_decl.zig new file mode 100644 index 0000000000..ccdbf67713 --- /dev/null +++ b/test/cases/compile_errors/closure_get_depends_on_failed_decl.zig @@ -0,0 +1,26 @@ +pub inline fn instanceRequestAdapter() void {} + +pub inline fn requestAdapter( + comptime callbackArg: fn () callconv(.Inline) void, +) void { + _ = (struct { + pub fn callback() callconv(.C) void { + callbackArg(); + } + }).callback; + instanceRequestAdapter(undefined); // note wrong number of arguments here +} + +inline fn foo() void {} + +pub export fn entry() void { + requestAdapter(foo); +} + +// error +// backend=stage2 +// target=native +// +// :11:5: error: expected 0 argument(s), found 1 +// :1:12: note: function declared here +// :17:19: note: called from here diff --git a/test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig b/test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig new file mode 100644 index 0000000000..dc533442fb --- /dev/null +++ b/test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig @@ -0,0 +1,24 @@ +fn Observable(comptime T: type) type { + return struct { + fn map(Src: T, Dst: anytype, function: fn (T) Dst) Dst { + _ = Src; + _ = function; + return Observable(Dst); + } + }; +} + +fn u32Tou64(x: u32) u64 { + _ = x; + return 0; +} + +pub export fn entry() void { + Observable(u32).map(u32, u64, u32Tou64(0)); +} + +// error +// backend=stage2 +// target=native +// +// :17:25: error: expected type 'u32', found 'type' |
