Commit 5de9aac749
Changed files (4)
src-self-hosted
src-self-hosted/type.zig
@@ -3,6 +3,7 @@ const Value = @import("value.zig").Value;
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const Target = std.Target;
+const Module = @import("Module.zig");
/// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication.
/// It's important for this type to be small.
@@ -52,7 +53,7 @@ pub const Type = extern union {
.bool => return .Bool,
.void => return .Void,
.type => return .Type,
- .anyerror => return .ErrorSet,
+ .error_set, .error_set_single, .anyerror => return .ErrorSet,
.comptime_int => return .ComptimeInt,
.comptime_float => return .ComptimeFloat,
.noreturn => return .NoReturn,
@@ -436,6 +437,8 @@ pub const Type = extern union {
};
return Type{ .ptr_otherwise = &new_payload.base };
},
+ .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
+ .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle),
}
}
@@ -657,6 +660,14 @@ pub const Type = extern union {
ty = payload.payload;
continue;
},
+ .error_set => {
+ const payload = @fieldParentPtr(Payload.ErrorSet, "base", ty.ptr_otherwise);
+ return out_stream.writeAll(std.mem.spanZ(payload.decl.name));
+ },
+ .error_set_single => {
+ const payload = @fieldParentPtr(Payload.ErrorSetSingle, "base", ty.ptr_otherwise);
+ return out_stream.print("error{{{}}}", .{payload.name});
+ },
}
unreachable;
}
@@ -753,6 +764,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> true,
// TODO lazy types
.array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
@@ -848,7 +861,11 @@ pub const Type = extern union {
.f128 => return 16,
.c_longdouble => return 16,
- .anyerror_void_error_union, .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
+ .error_set,
+ .error_set_single,
+ .anyerror_void_error_union,
+ .anyerror,
+ => return 2, // TODO revisit this when we have the concept of the error tag type
.array, .array_sentinel => return self.elemType().abiAlignment(target),
@@ -981,7 +998,11 @@ pub const Type = extern union {
.f128 => return 16,
.c_longdouble => return 16,
- .anyerror_void_error_union, .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
+ .error_set,
+ .error_set_single,
+ .anyerror_void_error_union,
+ .anyerror,
+ => return 2, // TODO revisit this when we have the concept of the error tag type
.int_signed, .int_unsigned => {
const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|
@@ -1084,6 +1105,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
.single_const_pointer,
@@ -1156,6 +1179,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
.const_slice,
@@ -1225,6 +1250,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
.single_const_pointer,
@@ -1303,6 +1330,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
.pointer => {
@@ -1418,6 +1447,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
.array => self.cast(Payload.Array).?.elem_type,
@@ -1543,6 +1574,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
.array => self.cast(Payload.Array).?.len,
@@ -1614,6 +1647,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
.array, .array_u8 => return null,
@@ -1683,6 +1718,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
.int_signed,
@@ -1755,6 +1792,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
.int_unsigned,
@@ -1817,6 +1856,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
.int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
@@ -1897,6 +1938,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
.usize,
@@ -2006,6 +2049,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
};
}
@@ -2081,6 +2126,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
}
}
@@ -2155,6 +2202,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
}
}
@@ -2229,6 +2278,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
};
}
@@ -2300,6 +2351,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
};
}
@@ -2371,6 +2424,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> unreachable,
};
}
@@ -2442,6 +2497,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> false,
};
}
@@ -2497,6 +2554,8 @@ pub const Type = extern union {
.anyframe_T,
.@"anyframe",
.error_union,
+ .error_set,
+ .error_set_single,
=> return null,
.void => return Value.initTag(.void_value),
@@ -2604,6 +2663,8 @@ pub const Type = extern union {
.@"anyframe",
.anyframe_T,
.anyerror_void_error_union,
+ .error_set,
+ .error_set_single,
=> return false,
.c_const_pointer,
@@ -2687,6 +2748,8 @@ pub const Type = extern union {
optional_single_const_pointer,
error_union,
anyframe_T,
+ error_set,
+ error_set_single,
pub const last_no_payload_tag = Tag.const_slice_u8;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -2781,6 +2844,19 @@ pub const Type = extern union {
return_type: Type,
};
+
+ pub const ErrorSet = struct {
+ base: Payload = .{ .tag = .error_set },
+
+ decl: *Module.Decl,
+ };
+
+ pub const ErrorSetSingle = struct {
+ base: Payload = .{ .tag = .error_set_single },
+
+ /// memory is owned by `Module`
+ name: []const u8,
+ };
};
};
src-self-hosted/value.zig
@@ -381,11 +381,9 @@ pub const Value = extern union {
}
/// Asserts that the value is representable as a type.
- pub fn toType(self: Value) Type {
+ pub fn toType(self: Value, allocator: *Allocator) !Type {
return switch (self.tag()) {
.ty => self.cast(Payload.Ty).?.ty,
- .int_type => @panic("TODO int type to type"),
-
.u8_type => Type.initTag(.u8),
.i8_type => Type.initTag(.i8),
.u16_type => Type.initTag(.u16),
@@ -427,7 +425,25 @@ pub const Value = extern union {
.const_slice_u8_type => Type.initTag(.const_slice_u8),
.enum_literal_type => Type.initTag(.enum_literal),
.anyframe_type => Type.initTag(.@"anyframe"),
- .error_set => @panic("TODO error set to type"),
+
+ .int_type => {
+ const payload = self.cast(Payload.IntType).?;
+ if (payload.signed) {
+ const new = try allocator.create(Type.Payload.IntSigned);
+ new.* = .{ .bits = payload.bits };
+ return Type.initPayload(&new.base);
+ } else {
+ const new = try allocator.create(Type.Payload.IntUnsigned);
+ new.* = .{ .bits = payload.bits };
+ return Type.initPayload(&new.base);
+ }
+ },
+ .error_set => {
+ const payload = self.cast(Payload.ErrorSet).?;
+ const new = try allocator.create(Type.Payload.ErrorSet);
+ new.* = .{ .decl = payload.decl };
+ return Type.initPayload(&new.base);
+ },
.undef,
.zero,
@@ -1579,6 +1595,7 @@ pub const Value = extern union {
// TODO revisit this when we have the concept of the error tag type
fields: std.StringHashMapUnmanaged(u16),
+ decl: *Module.Decl,
};
pub const Error = struct {
src-self-hosted/zir.zig
@@ -2016,7 +2016,7 @@ const EmitZIR = struct {
return self.emitUnnamedDecl(&as_inst.base);
},
.Type => {
- const ty = typed_value.val.toType();
+ const ty = try typed_value.val.toType(&self.arena.allocator);
return self.emitType(src, ty);
},
.Fn => {
src-self-hosted/zir_sema.zig
@@ -150,7 +150,7 @@ pub fn analyzeBodyValueAsType(mod: *Module, block_scope: *Scope.Block, body: zir
for (block_scope.instructions.items) |inst| {
if (inst.castTag(.ret)) |ret| {
const val = try mod.resolveConstValue(&block_scope.base, ret.operand);
- return val.toType();
+ return val.toType(block_scope.base.arena());
} else {
return mod.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{});
}
@@ -275,7 +275,7 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
const wanted_type = Type.initTag(.@"type");
const coerced_inst = try mod.coerce(scope, wanted_type, new_inst);
const val = try mod.resolveConstValue(scope, coerced_inst);
- return val.toType();
+ return val.toType(scope.arena());
}
fn resolveInt(mod: *Module, scope: *Scope, old_inst: *zir.Inst, dest_type: Type) !u64 {
@@ -745,7 +745,10 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
errdefer new_decl_arena.deinit();
const payload = try scope.arena().create(Value.Payload.ErrorSet);
- payload.* = .{ .fields = .{} };
+ payload.* = .{
+ .fields = .{},
+ .decl = undefined, // populated below
+ };
try payload.fields.ensureCapacity(&new_decl_arena.allocator, inst.positionals.fields.len);
for (inst.positionals.fields) |field_name| {
@@ -759,6 +762,7 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
.ty = Type.initTag(.type),
.val = Value.initPayload(&payload.base),
});
+ payload.decl = new_decl;
return mod.analyzeDeclRef(scope, inst.base.src, new_decl);
}
@@ -939,18 +943,17 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
_ = try mod.resolveConstValue(scope, object_ptr);
const result = try mod.analyzeDeref(scope, fieldptr.base.src, object_ptr, object_ptr.src);
const val = result.value().?;
- const child_type = val.toType();
+ const child_type = try val.toType(scope.arena());
switch (child_type.zigTypeTag()) {
.ErrorSet => {
// TODO resolve inferred error sets
const entry = if (val.cast(Value.Payload.ErrorSet)) |payload|
(payload.fields.getEntry(field_name) orelse
return mod.fail(scope, fieldptr.base.src, "no error named '{}' in '{}'", .{ field_name, child_type })).*
- else
- try mod.getErrorValue(field_name);
+ else try mod.getErrorValue(field_name);
const error_payload = try scope.arena().create(Value.Payload.Error);
- error_payload.* = .{
+ error_payload.* = .{
.name = entry.key,
.value = entry.value,
};
@@ -958,9 +961,14 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
const ref_payload = try scope.arena().create(Value.Payload.RefVal);
ref_payload.* = .{ .val = Value.initPayload(&error_payload.base) };
- // TODO if this is accessing the global error set create a `error{field_name}` type
+ const result_type = if (child_type.tag() == .anyerror) blk: {
+ const result_payload = try scope.arena().create(Type.Payload.ErrorSetSingle);
+ result_payload.* = .{ .name = entry.key };
+ break :blk Type.initPayload(&result_payload.base);
+ } else child_type;
+
return mod.constInst(scope, fieldptr.base.src, .{
- .ty = try mod.simplePtrType(scope, fieldptr.base.src, child_type, false, .One),
+ .ty = try mod.simplePtrType(scope, fieldptr.base.src, result_type, false, .One),
.val = Value.initPayload(&ref_payload.base),
});
},