Commit 39d5f44863
Changed files (18)
src/analyze.cpp
@@ -3367,7 +3367,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *so
}
ConstCastOnly types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
- ConstCastOnly result = {0};
+ ConstCastOnly result = {};
result.id = ConstCastResultIdOk;
if (expected_type == actual_type)
@@ -3465,7 +3465,7 @@ ConstCastOnly types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_t
if (result.id == ConstCastResultIdOk) {
result.id = ConstCastResultIdErrSet;
}
- result.data.error_set.errors.append(contained_error_entry);
+ result.data.error_set.missing_errors.append(contained_error_entry);
}
}
free(errors);
src/analyze.hpp
@@ -214,6 +214,8 @@ struct ConstCastErrSetMismatch {
ZigList<ErrorTableEntry *> missing_errors;
};
+struct ConstCastOnly;
+
struct ConstCastArg {
size_t arg_index;
ConstCastOnly *child;
@@ -238,6 +240,6 @@ struct ConstCastOnly {
} data;
};
-bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type);
+ConstCastOnly types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type);
#endif
src/ir.cpp
@@ -6424,12 +6424,23 @@ enum ImplicitCastMatchResult {
static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, TypeTableEntry *expected_type,
TypeTableEntry *actual_type, IrInstruction *value)
{
- if (types_match_const_cast_only(ira->codegen, expected_type, actual_type)) {
+ ConstCastOnly const_cast_result = types_match_const_cast_only(ira->codegen, expected_type, actual_type);
+ if (const_cast_result.id == ConstCastResultIdOk) {
return ImplicitCastMatchResultYes;
}
// if we got here with error sets, make an error showing the incompatibilities
- if (expected_typek
+ if (const_cast_result.id == ConstCastResultIdErrSet) {
+ ErrorMsg *msg = ir_add_error(ira, value,
+ buf_sprintf("expected '%s', found '%s'", buf_ptr(&expected_type->name), buf_ptr(&actual_type->name)));
+ for (size_t i = 0; i < const_cast_result.data.error_set.missing_errors.length; i += 1) {
+ ErrorTableEntry *error_entry = const_cast_result.data.error_set.missing_errors.at(i);
+ add_error_note(ira->codegen, msg, error_entry->decl_node,
+ buf_sprintf("'error.%s' not a member of destination error set", buf_ptr(&error_entry->name)));
+ }
+
+ return ImplicitCastMatchResultReportedError;
+ }
// implicit conversion from anything to var
if (expected_type->id == TypeTableEntryIdVar) {
@@ -6508,7 +6519,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
assert(ptr_type->id == TypeTableEntryIdPointer);
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type).id == ConstCastResultIdOk)
{
return ImplicitCastMatchResultYes;
}
@@ -6527,7 +6538,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
TypeTableEntry *array_type = actual_type->data.pointer.child_type;
if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, array_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, array_type->data.array.child_type).id == ConstCastResultIdOk)
{
return ImplicitCastMatchResultYes;
}
@@ -6543,7 +6554,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
expected_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == TypeTableEntryIdPointer);
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type).id == ConstCastResultIdOk)
{
return ImplicitCastMatchResultYes;
}
@@ -6558,7 +6569,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
expected_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == TypeTableEntryIdPointer);
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type).id == ConstCastResultIdOk)
{
return ImplicitCastMatchResultYes;
}
@@ -6638,7 +6649,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
// implicitly take a const pointer to something
if (!type_requires_comptime(actual_type)) {
TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true);
- if (types_match_const_cast_only(ira->codegen, expected_type, const_ptr_actual)) {
+ if (types_match_const_cast_only(ira->codegen, expected_type, const_ptr_actual).id == ConstCastResultIdOk) {
return ImplicitCastMatchResultYes;
}
}
@@ -6742,20 +6753,31 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
if (cur_is_superset) {
err_set_type = cur_type;
prev_inst = cur_inst;
+ assert(errors != nullptr);
continue;
}
// neither of them are supersets. so we invent a new error set type that is a union of both of them
err_set_type = get_error_set_union(ira->codegen, errors, cur_type, err_set_type);
+ assert(errors != nullptr);
continue;
} else if (cur_type->id == TypeTableEntryIdErrorUnion) {
+ if (err_set_type == ira->codegen->builtin_types.entry_global_error_set) {
+ prev_inst = cur_inst;
+ continue;
+ }
+ TypeTableEntry *cur_err_set_type = cur_type->data.error_union.err_set_type;
+ if (cur_err_set_type == ira->codegen->builtin_types.entry_global_error_set) {
+ err_set_type = ira->codegen->builtin_types.entry_global_error_set;
+ prev_inst = cur_inst;
+ continue;
+ }
// test if err_set_type is a subset of cur_type's error set
// unset everything in errors
for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
errors[error_entry->value] = nullptr;
}
- TypeTableEntry *cur_err_set_type = cur_type->data.error_union.err_set_type;
for (uint32_t i = 0; i < cur_err_set_type->data.error_set.err_count; i += 1) {
ErrorTableEntry *error_entry = cur_err_set_type->data.error_set.errors[i];
errors[error_entry->value] = error_entry;
@@ -6772,12 +6794,14 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
if (cur_is_superset) {
err_set_type = cur_err_set_type;
prev_inst = cur_inst;
+ assert(errors != nullptr);
continue;
}
// not a subset. invent new error set type, union of both of them
err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, err_set_type);
prev_inst = cur_inst;
+ assert(errors != nullptr);
continue;
} else {
prev_inst = cur_inst;
@@ -6820,15 +6844,16 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
}
// not a subset. invent new error set type, union of both of them
err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_type);
+ assert(errors != nullptr);
continue;
}
}
- if (types_match_const_cast_only(ira->codegen, prev_type, cur_type)) {
+ if (types_match_const_cast_only(ira->codegen, prev_type, cur_type).id == ConstCastResultIdOk) {
continue;
}
- if (types_match_const_cast_only(ira->codegen, cur_type, prev_type)) {
+ if (types_match_const_cast_only(ira->codegen, cur_type, prev_type).id == ConstCastResultIdOk) {
prev_inst = cur_inst;
continue;
}
@@ -6851,26 +6876,26 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
}
if (prev_type->id == TypeTableEntryIdErrorUnion &&
- types_match_const_cast_only(ira->codegen, prev_type->data.error_union.payload_type, cur_type))
+ types_match_const_cast_only(ira->codegen, prev_type->data.error_union.payload_type, cur_type).id == ConstCastResultIdOk)
{
continue;
}
if (cur_type->id == TypeTableEntryIdErrorUnion &&
- types_match_const_cast_only(ira->codegen, cur_type->data.error_union.payload_type, prev_type))
+ types_match_const_cast_only(ira->codegen, cur_type->data.error_union.payload_type, prev_type).id == ConstCastResultIdOk)
{
prev_inst = cur_inst;
continue;
}
if (prev_type->id == TypeTableEntryIdMaybe &&
- types_match_const_cast_only(ira->codegen, prev_type->data.maybe.child_type, cur_type))
+ types_match_const_cast_only(ira->codegen, prev_type->data.maybe.child_type, cur_type).id == ConstCastResultIdOk)
{
continue;
}
if (cur_type->id == TypeTableEntryIdMaybe &&
- types_match_const_cast_only(ira->codegen, cur_type->data.maybe.child_type, prev_type))
+ types_match_const_cast_only(ira->codegen, cur_type->data.maybe.child_type, prev_type).id == ConstCastResultIdOk)
{
prev_inst = cur_inst;
continue;
@@ -6908,7 +6933,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
cur_type->data.array.len != prev_type->data.array.len &&
- types_match_const_cast_only(ira->codegen, cur_type->data.array.child_type, prev_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, cur_type->data.array.child_type, prev_type->data.array.child_type).id == ConstCastResultIdOk)
{
convert_to_const_slice = true;
prev_inst = cur_inst;
@@ -6917,7 +6942,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
cur_type->data.array.len != prev_type->data.array.len &&
- types_match_const_cast_only(ira->codegen, prev_type->data.array.child_type, cur_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, prev_type->data.array.child_type, cur_type->data.array.child_type).id == ConstCastResultIdOk)
{
convert_to_const_slice = true;
continue;
@@ -6927,7 +6952,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
cur_type->data.array.len == 0) &&
types_match_const_cast_only(ira->codegen, prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
- cur_type->data.array.child_type))
+ cur_type->data.array.child_type).id == ConstCastResultIdOk)
{
convert_to_const_slice = false;
continue;
@@ -6937,7 +6962,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
prev_type->data.array.len == 0) &&
types_match_const_cast_only(ira->codegen, cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
- prev_type->data.array.child_type))
+ prev_type->data.array.child_type).id == ConstCastResultIdOk)
{
prev_inst = cur_inst;
convert_to_const_slice = false;
@@ -8059,7 +8084,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return value;
// explicit match or non-const to const
- if (types_match_const_cast_only(ira->codegen, wanted_type, actual_type)) {
+ if (types_match_const_cast_only(ira->codegen, wanted_type, actual_type).id == ConstCastResultIdOk) {
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
}
@@ -8105,7 +8130,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == TypeTableEntryIdPointer);
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type).id == ConstCastResultIdOk)
{
return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type);
}
@@ -8123,7 +8148,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
TypeTableEntry *array_type = actual_type->data.pointer.child_type;
if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, array_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, array_type->data.array.child_type).id == ConstCastResultIdOk)
{
return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type);
}
@@ -8139,7 +8164,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == TypeTableEntryIdPointer);
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type).id == ConstCastResultIdOk)
{
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
if (type_is_invalid(cast1->value.type))
@@ -8162,7 +8187,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == TypeTableEntryIdPointer);
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type).id == ConstCastResultIdOk)
{
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);
if (type_is_invalid(cast1->value.type))
@@ -8224,7 +8249,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// explicit cast from child type of maybe type to maybe type
if (wanted_type->id == TypeTableEntryIdMaybe) {
- if (types_match_const_cast_only(ira->codegen, wanted_type->data.maybe.child_type, actual_type)) {
+ if (types_match_const_cast_only(ira->codegen, wanted_type->data.maybe.child_type, actual_type).id == ConstCastResultIdOk) {
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
actual_type->id == TypeTableEntryIdNumLitFloat)
@@ -8246,7 +8271,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// explicit cast from child type of error type to error type
if (wanted_type->id == TypeTableEntryIdErrorUnion) {
- if (types_match_const_cast_only(ira->codegen, wanted_type->data.error_union.payload_type, actual_type)) {
+ if (types_match_const_cast_only(ira->codegen, wanted_type->data.error_union.payload_type, actual_type).id == ConstCastResultIdOk) {
return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
actual_type->id == TypeTableEntryIdNumLitFloat)
@@ -8268,7 +8293,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == TypeTableEntryIdPointer);
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
- types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ types_match_const_cast_only(ira->codegen, ptr_type->data.pointer.child_type, actual_type->data.array.child_type).id == ConstCastResultIdOk)
{
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
if (type_is_invalid(cast1->value.type))
@@ -8295,7 +8320,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
actual_type->id != TypeTableEntryIdMaybe)
{
TypeTableEntry *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
- if (types_match_const_cast_only(ira->codegen, wanted_child_type, actual_type) ||
+ if (types_match_const_cast_only(ira->codegen, wanted_child_type, actual_type).id == ConstCastResultIdOk ||
actual_type->id == TypeTableEntryIdNullLit ||
actual_type->id == TypeTableEntryIdNumLitInt ||
actual_type->id == TypeTableEntryIdNumLitFloat)
@@ -8445,7 +8470,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// explicit cast from something to const pointer of it
if (!type_requires_comptime(actual_type)) {
TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true);
- if (types_match_const_cast_only(ira->codegen, wanted_type, const_ptr_actual)) {
+ if (types_match_const_cast_only(ira->codegen, wanted_type, const_ptr_actual).id == ConstCastResultIdOk) {
return ir_analyze_cast_ref(ira, source_instr, value, wanted_type);
}
}
@@ -8473,7 +8498,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->value.type, value);
switch (result) {
case ImplicitCastMatchResultNo:
- ErrorMsg *msg = ir_add_error(ira, value,
+ ir_add_error(ira, value,
buf_sprintf("expected type '%s', found '%s'",
buf_ptr(&expected_type->name),
buf_ptr(&value->value.type->name)));
std/debug/index.zig
@@ -209,8 +209,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a
try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n");
}
} else |err| switch (err) {
- error.EndOfFile, error.PathNotFound => {},
- else => return err,
+ error.EndOfFile => {},
}
} else |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => {
std/fmt/index.zig
@@ -195,7 +195,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@
const T = @typeOf(value);
switch (@typeId(T)) {
builtin.TypeId.Int => {
- return formatInt(value, 10, false, 0, context, output);
+ return formatInt(value, 10, false, 0, context, Errors, output);
},
builtin.TypeId.Float => {
return formatFloat(value, context, output);
@@ -290,7 +290,7 @@ pub fn formatFloat(value: var, context: var, comptime Errors: type, output: fn(@
if (float_decimal.exp != 1) {
try output(context, "e");
- try formatInt(float_decimal.exp - 1, 10, false, 0, context, output);
+ try formatInt(float_decimal.exp - 1, 10, false, 0, context, Errors, output);
}
}
@@ -336,12 +336,12 @@ pub fn formatFloatDecimal(value: var, precision: usize, context: var, comptime E
pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
- context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)errors!void) errors!void
+ context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
{
if (@typeOf(value).is_signed) {
- return formatIntSigned(value, base, uppercase, width, context, output);
+ return formatIntSigned(value, base, uppercase, width, context, Errors, output);
} else {
- return formatIntUnsigned(value, base, uppercase, width, context, output);
+ return formatIntUnsigned(value, base, uppercase, width, context, Errors, output);
}
}
@@ -354,15 +354,15 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
try output(context, (&minus_sign)[0..1]);
const new_value = uint(-(value + 1)) + 1;
const new_width = if (width == 0) 0 else (width - 1);
- return formatIntUnsigned(new_value, base, uppercase, new_width, context, output);
+ return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
} else if (width == 0) {
- return formatIntUnsigned(uint(value), base, uppercase, width, context, output);
+ return formatIntUnsigned(uint(value), base, uppercase, width, context, Errors, output);
} else {
const plus_sign: u8 = '+';
try output(context, (&plus_sign)[0..1]);
const new_value = uint(value);
const new_width = if (width == 0) 0 else (width - 1);
- return formatIntUnsigned(new_value, base, uppercase, new_width, context, output);
+ return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
}
}
@@ -410,7 +410,7 @@ pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width:
.out_buf = out_buf,
.index = 0,
};
- formatInt(value, base, uppercase, width, &context, formatIntCallback) catch unreachable;
+ formatInt(value, base, uppercase, width, &context, error{}, formatIntCallback) catch unreachable;
return context.index;
}
const FormatIntBuf = struct {
@@ -446,7 +446,14 @@ test "fmt.parseInt" {
assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
}
-pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) !T {
+const ParseUnsignedError = error {
+ /// The result cannot fit in the type specified
+ Overflow,
+ /// The input had a byte that was not a digit
+ InvalidCharacter,
+};
+
+pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsignedError!T {
var x: T = 0;
for (buf) |c| {
@@ -458,16 +465,16 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) !T {
return x;
}
-fn charToDigit(c: u8, radix: u8) !u8 {
+fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
const value = switch (c) {
'0' ... '9' => c - '0',
'A' ... 'Z' => c - 'A' + 10,
'a' ... 'z' => c - 'a' + 10,
- else => return error.InvalidChar,
+ else => return error.InvalidCharacter,
};
if (value >= radix)
- return error.InvalidChar;
+ return error.InvalidCharacter;
return value;
}
std/math/index.zig
@@ -191,17 +191,17 @@ test "math.max" {
assert(max(i32(-1), i32(2)) == 2);
}
-pub fn mul(comptime T: type, a: T, b: T) !T {
+pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) {
var answer: T = undefined;
return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer;
}
-pub fn add(comptime T: type, a: T, b: T) !T {
+pub fn add(comptime T: type, a: T, b: T) (error{Overflow}!T) {
var answer: T = undefined;
return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
}
-pub fn sub(comptime T: type, a: T, b: T) !T {
+pub fn sub(comptime T: type, a: T, b: T) (error{Overflow}!T) {
var answer: T = undefined;
return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer;
}
test/cases/cast.zig
@@ -74,7 +74,7 @@ test "string literal to &const []const u8" {
assert(mem.eql(u8, *x, "hello"));
}
-test "implicitly cast from T to %?T" {
+test "implicitly cast from T to error!?T" {
castToMaybeTypeError(1);
comptime castToMaybeTypeError(1);
}
@@ -83,37 +83,37 @@ const A = struct {
};
fn castToMaybeTypeError(z: i32) void {
const x = i32(1);
- const y: %?i32 = x;
+ const y: error!?i32 = x;
assert(??(try y) == 1);
const f = z;
- const g: %?i32 = f;
+ const g: error!?i32 = f;
const a = A{ .a = z };
- const b: %?A = a;
+ const b: error!?A = a;
assert((??(b catch unreachable)).a == 1);
}
-test "implicitly cast from int to %?T" {
+test "implicitly cast from int to error!?T" {
implicitIntLitToMaybe();
comptime implicitIntLitToMaybe();
}
fn implicitIntLitToMaybe() void {
const f: ?i32 = 1;
- const g: %?i32 = 1;
+ const g: error!?i32 = 1;
}
-test "return null from fn() %?&T" {
+test "return null from fn() error!?&T" {
const a = returnNullFromMaybeTypeErrorRef();
const b = returnNullLitFromMaybeTypeErrorRef();
assert((try a) == null and (try b) == null);
}
-fn returnNullFromMaybeTypeErrorRef() !?&A {
+fn returnNullFromMaybeTypeErrorRef() error!?&A {
const a: ?&A = null;
return a;
}
-fn returnNullLitFromMaybeTypeErrorRef() !?&A {
+fn returnNullLitFromMaybeTypeErrorRef() error!?&A {
return null;
}
@@ -160,7 +160,7 @@ fn castToMaybeSlice() ?[]const u8 {
}
-test "implicitly cast from [0]T to %[]T" {
+test "implicitly cast from [0]T to error![]T" {
testCastZeroArrayToErrSliceMut();
comptime testCastZeroArrayToErrSliceMut();
}
@@ -169,11 +169,11 @@ fn testCastZeroArrayToErrSliceMut() void {
assert((gimmeErrOrSlice() catch unreachable).len == 0);
}
-fn gimmeErrOrSlice() ![]u8 {
+fn gimmeErrOrSlice() error![]u8 {
return []u8{};
}
-test "peer type resolution: [0]u8, []const u8, and %[]u8" {
+test "peer type resolution: [0]u8, []const u8, and error![]u8" {
{
var data = "hi";
const slice = data[0..];
@@ -187,7 +187,7 @@ test "peer type resolution: [0]u8, []const u8, and %[]u8" {
assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
}
-fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) ![]u8 {
+fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) error![]u8 {
if (a) {
return []u8{};
}
@@ -229,7 +229,7 @@ fn foo(args: ...) void {
test "peer type resolution: error and [N]T" {
- // TODO: implicit %T to %U where T can implicitly cast to U
+ // TODO: implicit error!T to error!U where T can implicitly cast to U
//assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
//comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
@@ -237,13 +237,13 @@ test "peer type resolution: error and [N]T" {
comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
}
-//fn testPeerErrorAndArray(x: u8) ![]const u8 {
+//fn testPeerErrorAndArray(x: u8) error![]const u8 {
// return switch (x) {
// 0x00 => "OK",
// else => error.BadValue,
// };
//}
-fn testPeerErrorAndArray2(x: u8) ![]const u8 {
+fn testPeerErrorAndArray2(x: u8) error![]const u8 {
return switch (x) {
0x00 => "OK",
0x01 => "OKK",
test/cases/enum_with_members.zig
@@ -6,7 +6,7 @@ const ET = union(enum) {
SINT: i32,
UINT: u32,
- pub fn print(a: &const ET, buf: []u8) !usize {
+ pub fn print(a: &const ET, buf: []u8) error!usize {
return switch (*a) {
ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
test/cases/error.zig
@@ -1,16 +1,16 @@
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
-pub fn foo() !i32 {
+pub fn foo() error!i32 {
const x = try bar();
return x + 1;
}
-pub fn bar() !i32 {
+pub fn bar() error!i32 {
return 13;
}
-pub fn baz() !i32 {
+pub fn baz() error!i32 {
const y = foo() catch 1234;
return y + 1;
}
@@ -50,7 +50,7 @@ test "error binary operator" {
assert(a == 3);
assert(b == 10);
}
-fn errBinaryOperatorG(x: bool) !isize {
+fn errBinaryOperatorG(x: bool) error!isize {
return if (x) error.ItBroke else isize(10);
}
@@ -59,18 +59,18 @@ test "unwrap simple value from error" {
const i = unwrapSimpleValueFromErrorDo() catch unreachable;
assert(i == 13);
}
-fn unwrapSimpleValueFromErrorDo() %isize { return 13; }
+fn unwrapSimpleValueFromErrorDo() error!isize { return 13; }
test "error return in assignment" {
doErrReturnInAssignment() catch unreachable;
}
-fn doErrReturnInAssignment() !void {
+fn doErrReturnInAssignment() error!void {
var x : i32 = undefined;
x = try makeANonErr();
}
-fn makeANonErr() !i32 {
+fn makeANonErr() error!i32 {
return 1;
}
test/cases/ir_block_deps.zig
@@ -11,7 +11,7 @@ fn foo(id: u64) !i32 {
};
}
-fn getErrInt() %i32 { return 0; }
+fn getErrInt() error!i32 { return 0; }
test "ir block deps" {
assert((foo(1) catch unreachable) == 0);
test/cases/misc.zig
@@ -262,7 +262,7 @@ test "generic malloc free" {
memFree(u8, a);
}
const some_mem : [100]u8 = undefined;
-fn memAlloc(comptime T: type, n: usize) ![]T {
+fn memAlloc(comptime T: type, n: usize) error![]T {
return @ptrCast(&T, &some_mem[0])[0..n];
}
fn memFree(comptime T: type, memory: []T) void { }
@@ -419,7 +419,7 @@ test "cast slice to u8 slice" {
test "pointer to void return type" {
testPointerToVoidReturnType() catch unreachable;
}
-fn testPointerToVoidReturnType() !void {
+fn testPointerToVoidReturnType() error!void {
const a = testPointerToVoidReturnType2();
return *a;
}
@@ -475,8 +475,8 @@ test "@typeId" {
assert(@typeId(@typeOf(undefined)) == Tid.UndefinedLiteral);
assert(@typeId(@typeOf(null)) == Tid.NullLiteral);
assert(@typeId(?i32) == Tid.Nullable);
- assert(@typeId(%i32) == Tid.ErrorUnion);
- assert(@typeId(error) == Tid.Error);
+ assert(@typeId(error!i32) == Tid.ErrorUnion);
+ assert(@typeId(error) == Tid.ErrorSet);
assert(@typeId(AnEnum) == Tid.Enum);
assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
assert(@typeId(AUnionEnum) == Tid.Union);
test/cases/reflection.zig
@@ -5,7 +5,7 @@ test "reflection: array, pointer, nullable, error union type child" {
comptime {
assert(([10]u8).Child == u8);
assert((&u8).Child == u8);
- assert((%u8).Child == u8);
+ assert((error!u8).Payload == u8);
assert((?u8).Child == u8);
}
}
test/cases/switch.zig
@@ -225,7 +225,7 @@ fn switchWithUnreachable(x: i32) i32 {
return 10;
}
-fn return_a_number() !i32 {
+fn return_a_number() error!i32 {
return 1;
}
test/cases/switch_prong_err_enum.zig
@@ -2,7 +2,7 @@ const assert = @import("std").debug.assert;
var read_count: u64 = 0;
-fn readOnce() !u64 {
+fn readOnce() error!u64 {
read_count += 1;
return read_count;
}
@@ -12,7 +12,7 @@ const FormValue = union(enum) {
Other: bool,
};
-fn doThing(form_id: u64) !FormValue {
+fn doThing(form_id: u64) error!FormValue {
return switch (form_id) {
17 => FormValue { .Address = try readOnce() },
else => error.InvalidDebugInfo,
test/cases/try.zig
@@ -17,7 +17,7 @@ fn tryOnErrorUnionImpl() void {
assert(x == 11);
}
-fn returnsTen() !i32 {
+fn returnsTen() error!i32 {
return 10;
}
@@ -29,7 +29,7 @@ test "try without vars" {
assert(result2 == 1);
}
-fn failIfTrue(ok: bool) !void {
+fn failIfTrue(ok: bool) error!void {
if (ok) {
return error.ItBroke;
} else {
test/cases/union.zig
@@ -13,7 +13,7 @@ const Agg = struct {
const v1 = Value { .Int = 1234 };
const v2 = Value { .Array = []u8{3} ** 9 };
-const err = (%Agg)(Agg {
+const err = (error!Agg)(Agg {
.val1 = v1,
.val2 = v2,
});
test/cases/while.zig
@@ -50,7 +50,7 @@ fn runContinueAndBreakTest() void {
test "return with implicit cast from while loop" {
returnWithImplicitCastFromWhileLoopTest() catch unreachable;
}
-fn returnWithImplicitCastFromWhileLoopTest() !void {
+fn returnWithImplicitCastFromWhileLoopTest() error!void {
while (true) {
return;
}
@@ -116,7 +116,7 @@ test "while with error union condition" {
}
var numbers_left: i32 = undefined;
-fn getNumberOrErr() !i32 {
+fn getNumberOrErr() error!i32 {
return if (numbers_left == 0)
error.OutOfNumbers
else x: {
@@ -204,7 +204,7 @@ fn testContinueOuter() void {
fn returnNull() ?i32 { return null; }
fn returnMaybe(x: i32) ?i32 { return x; }
-fn returnError() %i32 { return error.YouWantedAnError; }
-fn returnSuccess(x: i32) %i32 { return x; }
+fn returnError() error!i32 { return error.YouWantedAnError; }
+fn returnSuccess(x: i32) error!i32 { return x; }
fn returnFalse() bool { return false; }
fn returnTrue() bool { return true; }
TODO
@@ -1,6 +1,15 @@
-sed -i 's/\(\bfn .*) \)%\(.*{\)$/\1!\2/g' $(find .. -name "*.zig")
+sed -i 's/\(\bfn .*) \)%\(.*{\)$/\1!\2/g' $(find . -name "*.zig")
-comptime assert(error{} ! i32 == i32);
+the literal translation of `%T` to this new code is `error!T`.
+however this would not take advantage of error sets. It's
+recommended to generally have all your functions which return possible
+errors to use error set inference, like this:
+
+fn foo() !void {
+
+}
+
+then you can return void, or any error, and the error set is inferred.
// TODO this is an explicit cast and should actually coerce the type
erorr set casting