parent
6d793c0ea3
commit
1cf7511dc9
@ -212,6 +212,43 @@ static uint8_t bits_needed_for_unsigned(uint64_t x) {
|
||||
return (upper >= x) ? base : (base + 1);
|
||||
}
|
||||
|
||||
AstNode *type_decl_node(TypeTableEntry *type_entry) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdStruct:
|
||||
return type_entry->data.structure.decl_node;
|
||||
case TypeTableEntryIdEnum:
|
||||
return type_entry->data.enumeration.decl_node;
|
||||
case TypeTableEntryIdUnion:
|
||||
return type_entry->data.unionation.decl_node;
|
||||
case TypeTableEntryIdOpaque:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdPromise:
|
||||
return nullptr;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
bool type_is_complete(TypeTableEntry *type_entry) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
|
@ -202,5 +202,6 @@ uint32_t get_coro_frame_align_bytes(CodeGen *g);
|
||||
bool fn_type_can_fail(FnTypeId *fn_type_id);
|
||||
bool type_can_fail(TypeTableEntry *type_entry);
|
||||
bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type);
|
||||
AstNode *type_decl_node(TypeTableEntry *type_entry);
|
||||
|
||||
#endif
|
||||
|
47
src/ir.cpp
47
src/ir.cpp
@ -82,6 +82,7 @@ struct ConstCastSliceMismatch;
|
||||
struct ConstCastErrUnionErrSetMismatch;
|
||||
struct ConstCastErrUnionPayloadMismatch;
|
||||
struct ConstCastErrSetMismatch;
|
||||
struct ConstCastTypeMismatch;
|
||||
|
||||
struct ConstCastOnly {
|
||||
ConstCastResultId id;
|
||||
@ -92,6 +93,7 @@ struct ConstCastOnly {
|
||||
ConstCastOptionalMismatch *optional;
|
||||
ConstCastErrUnionPayloadMismatch *error_union_payload;
|
||||
ConstCastErrUnionErrSetMismatch *error_union_error_set;
|
||||
ConstCastTypeMismatch *type_mismatch;
|
||||
ConstCastOnly *return_type;
|
||||
ConstCastOnly *async_allocator_type;
|
||||
ConstCastOnly *null_wrap_ptr_child;
|
||||
@ -100,6 +102,11 @@ struct ConstCastOnly {
|
||||
} data;
|
||||
};
|
||||
|
||||
struct ConstCastTypeMismatch {
|
||||
TypeTableEntry *wanted_type;
|
||||
TypeTableEntry *actual_type;
|
||||
};
|
||||
|
||||
struct ConstCastOptionalMismatch {
|
||||
ConstCastOnly child;
|
||||
TypeTableEntry *wanted_child;
|
||||
@ -8128,15 +8135,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
|
||||
}
|
||||
|
||||
// pointer const
|
||||
if (wanted_type->id == TypeTableEntryIdPointer &&
|
||||
actual_type->id == TypeTableEntryIdPointer &&
|
||||
(actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
|
||||
(!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
|
||||
(!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
|
||||
actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
|
||||
actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&
|
||||
actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment)
|
||||
{
|
||||
if (wanted_type->id == TypeTableEntryIdPointer && actual_type->id == TypeTableEntryIdPointer) {
|
||||
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
|
||||
actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
|
||||
if (child.id != ConstCastResultIdOk) {
|
||||
@ -8145,8 +8144,17 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
|
||||
result.data.pointer_mismatch->child = child;
|
||||
result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
|
||||
result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
|
||||
return result;
|
||||
}
|
||||
if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
|
||||
(!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
|
||||
(!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
|
||||
actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
|
||||
actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&
|
||||
actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// slice const
|
||||
@ -8341,6 +8349,9 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
|
||||
}
|
||||
|
||||
result.id = ConstCastResultIdType;
|
||||
result.data.type_mismatch = allocate_nonzero<ConstCastTypeMismatch>(1);
|
||||
result.data.type_mismatch->wanted_type = wanted_type;
|
||||
result.data.type_mismatch->actual_type = actual_type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -10154,6 +10165,21 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
|
||||
report_recursive_error(ira, source_node, &cast_result->data.error_union_payload->child, msg);
|
||||
break;
|
||||
}
|
||||
case ConstCastResultIdType: {
|
||||
AstNode *wanted_decl_node = type_decl_node(cast_result->data.type_mismatch->wanted_type);
|
||||
AstNode *actual_decl_node = type_decl_node(cast_result->data.type_mismatch->actual_type);
|
||||
if (wanted_decl_node != nullptr) {
|
||||
add_error_note(ira->codegen, parent_msg, wanted_decl_node,
|
||||
buf_sprintf("%s declared here",
|
||||
buf_ptr(&cast_result->data.type_mismatch->wanted_type->name)));
|
||||
}
|
||||
if (actual_decl_node != nullptr) {
|
||||
add_error_note(ira->codegen, parent_msg, actual_decl_node,
|
||||
buf_sprintf("%s declared here",
|
||||
buf_ptr(&cast_result->data.type_mismatch->actual_type->name)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConstCastResultIdFnAlign: // TODO
|
||||
case ConstCastResultIdFnCC: // TODO
|
||||
case ConstCastResultIdFnVarArgs: // TODO
|
||||
@ -10163,7 +10189,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
|
||||
case ConstCastResultIdFnGenericArgCount: // TODO
|
||||
case ConstCastResultIdFnArg: // TODO
|
||||
case ConstCastResultIdFnArgNoAlias: // TODO
|
||||
case ConstCastResultIdType: // TODO
|
||||
case ConstCastResultIdUnresolvedInferredErrSet: // TODO
|
||||
case ConstCastResultIdAsyncAllocatorType: // TODO
|
||||
case ConstCastResultIdNullWrapPtr: // TODO
|
||||
|
@ -1,6 +1,40 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.addCase(x: {
|
||||
const tc = cases.create(
|
||||
"wrong same named struct",
|
||||
\\const a = @import("a.zig");
|
||||
\\const b = @import("b.zig");
|
||||
\\
|
||||
\\export fn entry() void {
|
||||
\\ var a1: a.Foo = undefined;
|
||||
\\ bar(&a1);
|
||||
\\}
|
||||
\\
|
||||
\\fn bar(x: *b.Foo) void {}
|
||||
,
|
||||
".tmp_source.zig:6:10: error: expected type '*Foo', found '*Foo'",
|
||||
".tmp_source.zig:6:10: note: pointer type child 'Foo' cannot cast into pointer type child 'Foo'",
|
||||
"a.zig:1:17: note: Foo declared here",
|
||||
"b.zig:1:17: note: Foo declared here",
|
||||
);
|
||||
|
||||
tc.addSourceFile("a.zig",
|
||||
\\pub const Foo = struct {
|
||||
\\ x: i32,
|
||||
\\};
|
||||
);
|
||||
|
||||
tc.addSourceFile("b.zig",
|
||||
\\pub const Foo = struct {
|
||||
\\ z: f64,
|
||||
\\};
|
||||
);
|
||||
|
||||
break :x tc;
|
||||
});
|
||||
|
||||
cases.add(
|
||||
"enum field value references enum",
|
||||
\\pub const Foo = extern enum {
|
||||
@ -358,9 +392,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
".tmp_source.zig:3:14: note: other value is here",
|
||||
);
|
||||
|
||||
|
||||
cases.add(
|
||||
"invalid cast from integral type to enum",
|
||||
cases.add("invalid cast from integral type to enum",
|
||||
\\const E = enum(usize) { One, Two };
|
||||
\\
|
||||
\\export fn entry() void {
|
||||
@ -372,9 +404,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ E.One => {},
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:9:10: error: expected type 'usize', found 'E'"
|
||||
);
|
||||
, ".tmp_source.zig:9:10: error: expected type 'usize', found 'E'");
|
||||
|
||||
cases.add(
|
||||
"range operator in switch used on error set",
|
||||
|
Loading…
x
Reference in New Issue
Block a user