aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2021-12-17 03:40:48 +0100
committerRobin Voetter <robin@voetter.nl>2021-12-21 01:41:50 +0100
commita2958a4ede0af4b4559eeb142c0400ae640db63e (patch)
treed70bec5423b9f712e010657509bd45407db871ba /src/Module.zig
parentb2343e63bd06d1312ca80745236bb42358062115 (diff)
downloadzig-a2958a4ede0af4b4559eeb142c0400ae640db63e.tar.gz
zig-a2958a4ede0af4b4559eeb142c0400ae640db63e.zip
stage2: allow multiple inferred error sets per Fn
This allows the inferred error set of comptime and inline invocations to be resolved separately from the inferred error set of the runtime version or other comptime/inline invocations.
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig112
1 files changed, 65 insertions, 47 deletions
diff --git a/src/Module.zig b/src/Module.zig
index b5d856efd0..7031dc20a5 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -1207,23 +1207,9 @@ pub const Fn = struct {
is_cold: bool = false,
is_noinline: bool = false,
- /// These fields are used to keep track of any dependencies related to functions
- /// that return inferred error sets. It's values are not used when the function
- /// does not return an inferred error set.
- inferred_error_set: struct {
- /// All currently known errors that this function returns. This includes direct additions
- /// via `return error.Foo;`, and possibly also errors that are returned from any dependent functions.
- /// When the inferred error set is fully resolved, this map contains all the errors that the function might return.
- errors: std.StringHashMapUnmanaged(void) = .{},
-
- /// Other functions with inferred error sets which the inferred error set of this
- /// function should include.
- functions: std.AutoHashMapUnmanaged(*Fn, void) = .{},
-
- /// Whether the function returned anyerror. This is true if either of the dependent functions
- /// returns anyerror.
- is_anyerror: bool = false,
- } = .{},
+ /// Any inferred error sets that this function owns, both it's own inferred error set and
+ /// inferred error sets of any inline/comptime functions called.
+ inferred_error_sets: InferredErrorSetList = .{},
pub const Analysis = enum {
queued,
@@ -1239,37 +1225,69 @@ pub const Fn = struct {
success,
};
- pub fn deinit(func: *Fn, gpa: Allocator) void {
- func.inferred_error_set.errors.deinit(gpa);
- func.inferred_error_set.functions.deinit(gpa);
- }
+ /// This struct is used to keep track of any dependencies related to functions instances
+ /// that return inferred error sets. Note that a function may be associated to multiple different error sets,
+ /// for example an inferred error set which this function returns, but also any inferred error sets
+ /// of called inline or comptime functions.
+ pub const InferredErrorSet = struct {
+ /// The function from which this error set originates.
+ /// Note: may be the function itself.
+ func: *Fn,
- pub fn addErrorSet(func: *Fn, gpa: Allocator, err_set_ty: Type) !void {
- switch (err_set_ty.tag()) {
- .error_set => {
- const names = err_set_ty.castTag(.error_set).?.data.names.keys();
- for (names) |name| {
- try func.inferred_error_set.errors.put(gpa, name, {});
- }
- },
- .error_set_single => {
- const name = err_set_ty.castTag(.error_set_single).?.data;
- try func.inferred_error_set.errors.put(gpa, name, {});
- },
- .error_set_inferred => {
- const dependent_func = err_set_ty.castTag(.error_set_inferred).?.data;
- try func.inferred_error_set.functions.put(gpa, dependent_func, {});
- },
- .error_set_merged => {
- const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
- for (names) |name| {
- try func.inferred_error_set.errors.put(gpa, name, {});
- }
- },
- .anyerror => {
- func.inferred_error_set.is_anyerror = true;
- },
- else => unreachable,
+ /// All currently known errors that this error set contains. This includes direct additions
+ /// via `return error.Foo;`, and possibly also errors that are returned from any dependent functions.
+ /// When the inferred error set is fully resolved, this map contains all the errors that the function might return.
+ errors: std.StringHashMapUnmanaged(void) = .{},
+
+ /// Other functions with inferred error sets which the inferred error set of this
+ /// function should include.
+ functions: std.AutoHashMapUnmanaged(*Fn, void) = .{},
+
+ /// Whether the function returned anyerror. This is true if either of the dependent functions
+ /// returns anyerror.
+ is_anyerror: bool = false,
+
+ pub fn addErrorSet(self: *InferredErrorSet, gpa: Allocator, err_set_ty: Type) !void {
+ switch (err_set_ty.tag()) {
+ .error_set => {
+ const names = err_set_ty.castTag(.error_set).?.data.names.keys();
+ for (names) |name| {
+ try self.errors.put(gpa, name, {});
+ }
+ },
+ .error_set_single => {
+ const name = err_set_ty.castTag(.error_set_single).?.data;
+ try self.errors.put(gpa, name, {});
+ },
+ .error_set_inferred => {
+ const dependent_func = err_set_ty.castTag(.error_set_inferred).?.data.func;
+ try self.functions.put(gpa, dependent_func, {});
+ },
+ .error_set_merged => {
+ const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
+ for (names) |name| {
+ try self.errors.put(gpa, name, {});
+ }
+ },
+ .anyerror => {
+ self.is_anyerror = true;
+ },
+ else => unreachable,
+ }
+ }
+ };
+
+ pub const InferredErrorSetList = std.SinglyLinkedList(InferredErrorSet);
+ pub const InferredErrorSetListNode = InferredErrorSetList.Node;
+
+ pub fn deinit(func: *Fn, gpa: Allocator) void {
+ var it = func.inferred_error_sets.first;
+ while (it) |node| {
+ const next = node.next;
+ node.data.errors.deinit(gpa);
+ node.data.functions.deinit(gpa);
+ gpa.destroy(node);
+ it = next;
}
}
};