authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-06 16:20:46-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-06 16:20:46-04:00
log1cf7511dc9d449473748675a5e734e81ea7c85c2
treee3703a3d1c89d8be15a721ba5b9e037a0da5db44
parent6d793c0ea3679fe420199676e92e435c81617258

add compile error notes for where struct definitions are

closes #1202

4 files changed, 110 insertions(+), 17 deletions(-)

src/analyze.cpp+37
...@@ -212,6 +212,43 @@ static uint8_t bits_needed_for_unsigned(uint64_t x) {...@@ -212,6 +212,43 @@ static uint8_t bits_needed_for_unsigned(uint64_t x) {
212 return (upper >= x) ? base : (base + 1);212 return (upper >= x) ? base : (base + 1);
213}213}
214214
215AstNode *type_decl_node(TypeTableEntry *type_entry) {
216 switch (type_entry->id) {
217 case TypeTableEntryIdInvalid:
218 zig_unreachable();
219 case TypeTableEntryIdStruct:
220 return type_entry->data.structure.decl_node;
221 case TypeTableEntryIdEnum:
222 return type_entry->data.enumeration.decl_node;
223 case TypeTableEntryIdUnion:
224 return type_entry->data.unionation.decl_node;
225 case TypeTableEntryIdOpaque:
226 case TypeTableEntryIdMetaType:
227 case TypeTableEntryIdVoid:
228 case TypeTableEntryIdBool:
229 case TypeTableEntryIdUnreachable:
230 case TypeTableEntryIdInt:
231 case TypeTableEntryIdFloat:
232 case TypeTableEntryIdPointer:
233 case TypeTableEntryIdArray:
234 case TypeTableEntryIdComptimeFloat:
235 case TypeTableEntryIdComptimeInt:
236 case TypeTableEntryIdUndefined:
237 case TypeTableEntryIdNull:
238 case TypeTableEntryIdOptional:
239 case TypeTableEntryIdErrorUnion:
240 case TypeTableEntryIdErrorSet:
241 case TypeTableEntryIdFn:
242 case TypeTableEntryIdNamespace:
243 case TypeTableEntryIdBlock:
244 case TypeTableEntryIdBoundFn:
245 case TypeTableEntryIdArgTuple:
246 case TypeTableEntryIdPromise:
247 return nullptr;
248 }
249 zig_unreachable();
250}
251
215bool type_is_complete(TypeTableEntry *type_entry) {252bool type_is_complete(TypeTableEntry *type_entry) {
216 switch (type_entry->id) {253 switch (type_entry->id) {
217 case TypeTableEntryIdInvalid:254 case TypeTableEntryIdInvalid:
src/analyze.hpp+1
...@@ -202,5 +202,6 @@ uint32_t get_coro_frame_align_bytes(CodeGen *g);...@@ -202,5 +202,6 @@ uint32_t get_coro_frame_align_bytes(CodeGen *g);
202bool fn_type_can_fail(FnTypeId *fn_type_id);202bool fn_type_can_fail(FnTypeId *fn_type_id);
203bool type_can_fail(TypeTableEntry *type_entry);203bool type_can_fail(TypeTableEntry *type_entry);
204bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type);204bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type);
205AstNode *type_decl_node(TypeTableEntry *type_entry);
205206
206#endif207#endif
src/ir.cpp+36-11
...@@ -82,6 +82,7 @@ struct ConstCastSliceMismatch;...@@ -82,6 +82,7 @@ struct ConstCastSliceMismatch;
82struct ConstCastErrUnionErrSetMismatch;82struct ConstCastErrUnionErrSetMismatch;
83struct ConstCastErrUnionPayloadMismatch;83struct ConstCastErrUnionPayloadMismatch;
84struct ConstCastErrSetMismatch;84struct ConstCastErrSetMismatch;
85struct ConstCastTypeMismatch;
8586
86struct ConstCastOnly {87struct ConstCastOnly {
87 ConstCastResultId id;88 ConstCastResultId id;
...@@ -92,6 +93,7 @@ struct ConstCastOnly {...@@ -92,6 +93,7 @@ struct ConstCastOnly {
92 ConstCastOptionalMismatch *optional;93 ConstCastOptionalMismatch *optional;
93 ConstCastErrUnionPayloadMismatch *error_union_payload;94 ConstCastErrUnionPayloadMismatch *error_union_payload;
94 ConstCastErrUnionErrSetMismatch *error_union_error_set;95 ConstCastErrUnionErrSetMismatch *error_union_error_set;
96 ConstCastTypeMismatch *type_mismatch;
95 ConstCastOnly *return_type;97 ConstCastOnly *return_type;
96 ConstCastOnly *async_allocator_type;98 ConstCastOnly *async_allocator_type;
97 ConstCastOnly *null_wrap_ptr_child;99 ConstCastOnly *null_wrap_ptr_child;
...@@ -100,6 +102,11 @@ struct ConstCastOnly {...@@ -100,6 +102,11 @@ struct ConstCastOnly {
100 } data;102 } data;
101};103};
102104
105struct ConstCastTypeMismatch {
106 TypeTableEntry *wanted_type;
107 TypeTableEntry *actual_type;
108};
109
103struct ConstCastOptionalMismatch {110struct ConstCastOptionalMismatch {
104 ConstCastOnly child;111 ConstCastOnly child;
105 TypeTableEntry *wanted_child;112 TypeTableEntry *wanted_child;
...@@ -8128,15 +8135,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry...@@ -8128,15 +8135,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
8128 }8135 }
81298136
8130 // pointer const8137 // pointer const
8131 if (wanted_type->id == TypeTableEntryIdPointer &&8138 if (wanted_type->id == TypeTableEntryIdPointer && actual_type->id == TypeTableEntryIdPointer) {
8132 actual_type->id == TypeTableEntryIdPointer &&
8133 (actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
8134 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8135 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
8136 actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
8137 actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&
8138 actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment)
8139 {
8140 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,8139 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8141 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);8140 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
8142 if (child.id != ConstCastResultIdOk) {8141 if (child.id != ConstCastResultIdOk) {
...@@ -8145,8 +8144,17 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry...@@ -8145,8 +8144,17 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
8145 result.data.pointer_mismatch->child = child;8144 result.data.pointer_mismatch->child = child;
8146 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;8145 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
8147 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;8146 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
8147 return result;
8148 }
8149 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
8150 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8151 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
8152 actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
8153 actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&
8154 actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment)
8155 {
8156 return result;
8148 }8157 }
8149 return result;
8150 }8158 }
81518159
8152 // slice const8160 // slice const
...@@ -8341,6 +8349,9 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry...@@ -8341,6 +8349,9 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
8341 }8349 }
83428350
8343 result.id = ConstCastResultIdType;8351 result.id = ConstCastResultIdType;
8352 result.data.type_mismatch = allocate_nonzero<ConstCastTypeMismatch>(1);
8353 result.data.type_mismatch->wanted_type = wanted_type;
8354 result.data.type_mismatch->actual_type = actual_type;
8344 return result;8355 return result;
8345}8356}
83468357
...@@ -10154,6 +10165,21 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10154,6 +10165,21 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10154 report_recursive_error(ira, source_node, &cast_result->data.error_union_payload->child, msg);10165 report_recursive_error(ira, source_node, &cast_result->data.error_union_payload->child, msg);
10155 break;10166 break;
10156 }10167 }
10168 case ConstCastResultIdType: {
10169 AstNode *wanted_decl_node = type_decl_node(cast_result->data.type_mismatch->wanted_type);
10170 AstNode *actual_decl_node = type_decl_node(cast_result->data.type_mismatch->actual_type);
10171 if (wanted_decl_node != nullptr) {
10172 add_error_note(ira->codegen, parent_msg, wanted_decl_node,
10173 buf_sprintf("%s declared here",
10174 buf_ptr(&cast_result->data.type_mismatch->wanted_type->name)));
10175 }
10176 if (actual_decl_node != nullptr) {
10177 add_error_note(ira->codegen, parent_msg, actual_decl_node,
10178 buf_sprintf("%s declared here",
10179 buf_ptr(&cast_result->data.type_mismatch->actual_type->name)));
10180 }
10181 break;
10182 }
10157 case ConstCastResultIdFnAlign: // TODO10183 case ConstCastResultIdFnAlign: // TODO
10158 case ConstCastResultIdFnCC: // TODO10184 case ConstCastResultIdFnCC: // TODO
10159 case ConstCastResultIdFnVarArgs: // TODO10185 case ConstCastResultIdFnVarArgs: // TODO
...@@ -10163,7 +10189,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10163,7 +10189,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10163 case ConstCastResultIdFnGenericArgCount: // TODO10189 case ConstCastResultIdFnGenericArgCount: // TODO
10164 case ConstCastResultIdFnArg: // TODO10190 case ConstCastResultIdFnArg: // TODO
10165 case ConstCastResultIdFnArgNoAlias: // TODO10191 case ConstCastResultIdFnArgNoAlias: // TODO
10166 case ConstCastResultIdType: // TODO
10167 case ConstCastResultIdUnresolvedInferredErrSet: // TODO10192 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
10168 case ConstCastResultIdAsyncAllocatorType: // TODO10193 case ConstCastResultIdAsyncAllocatorType: // TODO
10169 case ConstCastResultIdNullWrapPtr: // TODO10194 case ConstCastResultIdNullWrapPtr: // TODO
test/compile_errors.zig+36-6
...@@ -1,6 +1,40 @@...@@ -1,6 +1,40 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.addCase(x: {
5 const tc = cases.create(
6 "wrong same named struct",
7 \\const a = @import("a.zig");
8 \\const b = @import("b.zig");
9 \\
10 \\export fn entry() void {
11 \\ var a1: a.Foo = undefined;
12 \\ bar(&a1);
13 \\}
14 \\
15 \\fn bar(x: *b.Foo) void {}
16 ,
17 ".tmp_source.zig:6:10: error: expected type '*Foo', found '*Foo'",
18 ".tmp_source.zig:6:10: note: pointer type child 'Foo' cannot cast into pointer type child 'Foo'",
19 "a.zig:1:17: note: Foo declared here",
20 "b.zig:1:17: note: Foo declared here",
21 );
22
23 tc.addSourceFile("a.zig",
24 \\pub const Foo = struct {
25 \\ x: i32,
26 \\};
27 );
28
29 tc.addSourceFile("b.zig",
30 \\pub const Foo = struct {
31 \\ z: f64,
32 \\};
33 );
34
35 break :x tc;
36 });
37
4 cases.add(38 cases.add(
5 "enum field value references enum",39 "enum field value references enum",
6 \\pub const Foo = extern enum {40 \\pub const Foo = extern enum {
...@@ -358,9 +392,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -358,9 +392,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
358 ".tmp_source.zig:3:14: note: other value is here",392 ".tmp_source.zig:3:14: note: other value is here",
359 );393 );
360394
361395 cases.add("invalid cast from integral type to enum",
362 cases.add(
363 "invalid cast from integral type to enum",
364 \\const E = enum(usize) { One, Two };396 \\const E = enum(usize) { One, Two };
365 \\397 \\
366 \\export fn entry() void {398 \\export fn entry() void {
...@@ -372,9 +404,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -372,9 +404,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
372 \\ E.One => {},404 \\ E.One => {},
373 \\ }405 \\ }
374 \\}406 \\}
375 ,407 , ".tmp_source.zig:9:10: error: expected type 'usize', found 'E'");
376 ".tmp_source.zig:9:10: error: expected type 'usize', found 'E'"
377 );
378408
379 cases.add(409 cases.add(
380 "range operator in switch used on error set",410 "range operator in switch used on error set",