add compile error notes for where struct definitions are

closes #1202
This commit is contained in:
Andrew Kelley 2018-07-06 16:20:46 -04:00
parent 6d793c0ea3
commit 1cf7511dc9
4 changed files with 110 additions and 17 deletions

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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",