authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-19 18:51:46-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-19 18:51:46-04:00
log42db807f375d0c8fe248eebcb4eaeed71b43075d
tree2be4e6545f55e9c68abcd434249c64125c3c8a5e
parentee525c92a4c3bafa8f30c46e0303e0bca8f81860

remove redundant implicit casting code

and introduce better type mismatch errors closes #1061

2 files changed, 189 insertions(+), 394 deletions(-)

src/ir.cpp+178-386
......@@ -65,12 +65,7 @@ enum ConstCastResultId {
6565 ConstCastResultIdNullWrapPtr,
6666};
6767
68struct ConstCastErrSetMismatch {
69 ZigList<ErrorTableEntry *> missing_errors;
70};
71
7268struct ConstCastOnly;
73
7469struct ConstCastArg {
7570 size_t arg_index;
7671 ConstCastOnly *child;
......@@ -80,15 +75,22 @@ struct ConstCastArgNoAlias {
8075 size_t arg_index;
8176};
8277
78struct ConstCastOptionalMismatch;
79struct ConstCastPointerMismatch;
80struct ConstCastSliceMismatch;
81struct ConstCastErrUnionErrSetMismatch;
82struct ConstCastErrUnionPayloadMismatch;
83struct ConstCastErrSetMismatch;
84
8385struct ConstCastOnly {
8486 ConstCastResultId id;
8587 union {
86 ConstCastErrSetMismatch error_set;
87 ConstCastOnly *pointer_child;
88 ConstCastOnly *slice_child;
89 ConstCastOnly *optional_child;
90 ConstCastOnly *error_union_payload;
91 ConstCastOnly *error_union_error_set;
88 ConstCastErrSetMismatch *error_set_mismatch;
89 ConstCastPointerMismatch *pointer_mismatch;
90 ConstCastSliceMismatch *slice_mismatch;
91 ConstCastOptionalMismatch *optional;
92 ConstCastErrUnionPayloadMismatch *error_union_payload;
93 ConstCastErrUnionErrSetMismatch *error_union_error_set;
9294 ConstCastOnly *return_type;
9395 ConstCastOnly *async_allocator_type;
9496 ConstCastOnly *null_wrap_ptr_child;
......@@ -97,6 +99,39 @@ struct ConstCastOnly {
9799 } data;
98100};
99101
102struct ConstCastOptionalMismatch {
103 ConstCastOnly child;
104 TypeTableEntry *wanted_child;
105 TypeTableEntry *actual_child;
106};
107
108struct ConstCastPointerMismatch {
109 ConstCastOnly child;
110 TypeTableEntry *wanted_child;
111 TypeTableEntry *actual_child;
112};
113
114struct ConstCastSliceMismatch {
115 ConstCastOnly child;
116 TypeTableEntry *wanted_child;
117 TypeTableEntry *actual_child;
118};
119
120struct ConstCastErrUnionErrSetMismatch {
121 ConstCastOnly child;
122 TypeTableEntry *wanted_err_set;
123 TypeTableEntry *actual_err_set;
124};
125
126struct ConstCastErrUnionPayloadMismatch {
127 ConstCastOnly child;
128 TypeTableEntry *wanted_payload;
129 TypeTableEntry *actual_payload;
130};
131
132struct ConstCastErrSetMismatch {
133 ZigList<ErrorTableEntry *> missing_errors;
134};
100135
101136static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
102137static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);
......@@ -7972,8 +8007,10 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
79728007 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
79738008 if (child.id != ConstCastResultIdOk) {
79748009 result.id = ConstCastResultIdPointerChild;
7975 result.data.pointer_child = allocate_nonzero<ConstCastOnly>(1);
7976 *result.data.pointer_child = child;
8010 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
8011 result.data.pointer_mismatch->child = child;
8012 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
8013 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
79778014 }
79788015 return result;
79798016 }
......@@ -7992,8 +8029,10 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
79928029 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
79938030 if (child.id != ConstCastResultIdOk) {
79948031 result.id = ConstCastResultIdSliceChild;
7995 result.data.slice_child = allocate_nonzero<ConstCastOnly>(1);
7996 *result.data.slice_child = child;
8032 result.data.slice_mismatch = allocate_nonzero<ConstCastSliceMismatch>(1);
8033 result.data.slice_mismatch->child = child;
8034 result.data.slice_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
8035 result.data.slice_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
79978036 }
79988037 return result;
79998038 }
......@@ -8005,8 +8044,10 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
80058044 actual_type->data.maybe.child_type, source_node, wanted_is_mutable);
80068045 if (child.id != ConstCastResultIdOk) {
80078046 result.id = ConstCastResultIdOptionalChild;
8008 result.data.optional_child = allocate_nonzero<ConstCastOnly>(1);
8009 *result.data.optional_child = child;
8047 result.data.optional = allocate_nonzero<ConstCastOptionalMismatch>(1);
8048 result.data.optional->child = child;
8049 result.data.optional->wanted_child = wanted_type->data.maybe.child_type;
8050 result.data.optional->actual_child = actual_type->data.maybe.child_type;
80108051 }
80118052 return result;
80128053 }
......@@ -8017,16 +8058,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
80178058 actual_type->data.error_union.payload_type, source_node, wanted_is_mutable);
80188059 if (payload_child.id != ConstCastResultIdOk) {
80198060 result.id = ConstCastResultIdErrorUnionPayload;
8020 result.data.error_union_payload = allocate_nonzero<ConstCastOnly>(1);
8021 *result.data.error_union_payload = payload_child;
8061 result.data.error_union_payload = allocate_nonzero<ConstCastErrUnionPayloadMismatch>(1);
8062 result.data.error_union_payload->child = payload_child;
8063 result.data.error_union_payload->wanted_payload = wanted_type->data.error_union.payload_type;
8064 result.data.error_union_payload->actual_payload = actual_type->data.error_union.payload_type;
80228065 return result;
80238066 }
80248067 ConstCastOnly error_set_child = types_match_const_cast_only(ira, wanted_type->data.error_union.err_set_type,
80258068 actual_type->data.error_union.err_set_type, source_node, wanted_is_mutable);
80268069 if (error_set_child.id != ConstCastResultIdOk) {
80278070 result.id = ConstCastResultIdErrorUnionErrorSet;
8028 result.data.error_union_error_set = allocate_nonzero<ConstCastOnly>(1);
8029 *result.data.error_union_error_set = error_set_child;
8071 result.data.error_union_error_set = allocate_nonzero<ConstCastErrUnionErrSetMismatch>(1);
8072 result.data.error_union_error_set->child = error_set_child;
8073 result.data.error_union_error_set->wanted_err_set = wanted_type->data.error_union.err_set_type;
8074 result.data.error_union_error_set->actual_err_set = actual_type->data.error_union.err_set_type;
80308075 return result;
80318076 }
80328077 return result;
......@@ -8068,8 +8113,9 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
80688113 if (error_entry == nullptr) {
80698114 if (result.id == ConstCastResultIdOk) {
80708115 result.id = ConstCastResultIdErrSet;
8116 result.data.error_set_mismatch = allocate<ConstCastErrSetMismatch>(1);
80718117 }
8072 result.data.error_set.missing_errors.append(contained_error_entry);
8118 result.data.error_set_mismatch->missing_errors.append(contained_error_entry);
80738119 }
80748120 }
80758121 free(errors);
......@@ -8164,325 +8210,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
81648210 return result;
81658211}
81668212
8167enum ImplicitCastMatchResult {
8168 ImplicitCastMatchResultNo,
8169 ImplicitCastMatchResultYes,
8170 ImplicitCastMatchResultReportedError,
8171};
8172
8173static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, TypeTableEntry *wanted_type,
8174 TypeTableEntry *actual_type, IrInstruction *value)
8175{
8176 AstNode *source_node = value->source_node;
8177 ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,
8178 source_node, false);
8179 if (const_cast_result.id == ConstCastResultIdOk) {
8180 return ImplicitCastMatchResultYes;
8181 }
8182
8183 // if we got here with error sets, make an error showing the incompatibilities
8184 ZigList<ErrorTableEntry *> *missing_errors = nullptr;
8185 if (const_cast_result.id == ConstCastResultIdErrSet) {
8186 missing_errors = &const_cast_result.data.error_set.missing_errors;
8187 }
8188 if (const_cast_result.id == ConstCastResultIdErrorUnionErrorSet) {
8189 if (const_cast_result.data.error_union_error_set->id == ConstCastResultIdErrSet) {
8190 missing_errors = &const_cast_result.data.error_union_error_set->data.error_set.missing_errors;
8191 } else if (const_cast_result.data.error_union_error_set->id == ConstCastResultIdErrSetGlobal) {
8192 ErrorMsg *msg = ir_add_error(ira, value,
8193 buf_sprintf("expected '%s', found '%s'", buf_ptr(&wanted_type->name), buf_ptr(&actual_type->name)));
8194 add_error_note(ira->codegen, msg, value->source_node,
8195 buf_sprintf("unable to cast global error set into smaller set"));
8196 return ImplicitCastMatchResultReportedError;
8197 }
8198 } else if (const_cast_result.id == ConstCastResultIdErrSetGlobal) {
8199 ErrorMsg *msg = ir_add_error(ira, value,
8200 buf_sprintf("expected '%s', found '%s'", buf_ptr(&wanted_type->name), buf_ptr(&actual_type->name)));
8201 add_error_note(ira->codegen, msg, value->source_node,
8202 buf_sprintf("unable to cast global error set into smaller set"));
8203 return ImplicitCastMatchResultReportedError;
8204 }
8205 if (missing_errors != nullptr) {
8206 ErrorMsg *msg = ir_add_error(ira, value,
8207 buf_sprintf("expected '%s', found '%s'", buf_ptr(&wanted_type->name), buf_ptr(&actual_type->name)));
8208 for (size_t i = 0; i < missing_errors->length; i += 1) {
8209 ErrorTableEntry *error_entry = missing_errors->at(i);
8210 add_error_note(ira->codegen, msg, error_entry->decl_node,
8211 buf_sprintf("'error.%s' not a member of destination error set", buf_ptr(&error_entry->name)));
8212 }
8213
8214 return ImplicitCastMatchResultReportedError;
8215 }
8216
8217 // implicit conversion from ?T to ?U
8218 if (wanted_type->id == TypeTableEntryIdOptional && actual_type->id == TypeTableEntryIdOptional) {
8219 ImplicitCastMatchResult res = ir_types_match_with_implicit_cast(ira, wanted_type->data.maybe.child_type,
8220 actual_type->data.maybe.child_type, value);
8221 if (res != ImplicitCastMatchResultNo)
8222 return res;
8223 }
8224
8225 // implicit conversion from non maybe type to maybe type
8226 if (wanted_type->id == TypeTableEntryIdOptional) {
8227 ImplicitCastMatchResult res = ir_types_match_with_implicit_cast(ira, wanted_type->data.maybe.child_type,
8228 actual_type, value);
8229 if (res != ImplicitCastMatchResultNo)
8230 return res;
8231 }
8232
8233 // implicit conversion from null literal to maybe type
8234 if (wanted_type->id == TypeTableEntryIdOptional &&
8235 actual_type->id == TypeTableEntryIdNull)
8236 {
8237 return ImplicitCastMatchResultYes;
8238 }
8239
8240 // implicit T to U!T
8241 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
8242 ir_types_match_with_implicit_cast(ira, wanted_type->data.error_union.payload_type, actual_type, value))
8243 {
8244 return ImplicitCastMatchResultYes;
8245 }
8246
8247 // implicit conversion from error set to error union type
8248 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
8249 actual_type->id == TypeTableEntryIdErrorSet)
8250 {
8251 return ImplicitCastMatchResultYes;
8252 }
8253
8254 // implicit conversion from T to U!?T
8255 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
8256 wanted_type->data.error_union.payload_type->id == TypeTableEntryIdOptional &&
8257 ir_types_match_with_implicit_cast(ira,
8258 wanted_type->data.error_union.payload_type->data.maybe.child_type,
8259 actual_type, value))
8260 {
8261 return ImplicitCastMatchResultYes;
8262 }
8263
8264 // implicit widening conversion
8265 if (wanted_type->id == TypeTableEntryIdInt &&
8266 actual_type->id == TypeTableEntryIdInt &&
8267 wanted_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
8268 wanted_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
8269 {
8270 return ImplicitCastMatchResultYes;
8271 }
8272
8273 // small enough unsigned ints can get casted to large enough signed ints
8274 if (wanted_type->id == TypeTableEntryIdInt && wanted_type->data.integral.is_signed &&
8275 actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
8276 wanted_type->data.integral.bit_count > actual_type->data.integral.bit_count)
8277 {
8278 return ImplicitCastMatchResultYes;
8279 }
8280
8281 // implicit float widening conversion
8282 if (wanted_type->id == TypeTableEntryIdFloat &&
8283 actual_type->id == TypeTableEntryIdFloat &&
8284 wanted_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
8285 {
8286 return ImplicitCastMatchResultYes;
8287 }
8288
8289 // implicit [N]T to []const T
8290 if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) {
8291 TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
8292 assert(ptr_type->id == TypeTableEntryIdPointer);
8293
8294 if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
8295 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
8296 source_node, false).id == ConstCastResultIdOk)
8297 {
8298 return ImplicitCastMatchResultYes;
8299 }
8300 }
8301
8302 // implicit &const [N]T to []const T
8303 if (is_slice(wanted_type) &&
8304 actual_type->id == TypeTableEntryIdPointer &&
8305 actual_type->data.pointer.ptr_len == PtrLenSingle &&
8306 actual_type->data.pointer.is_const &&
8307 actual_type->data.pointer.child_type->id == TypeTableEntryIdArray)
8308 {
8309 TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
8310 assert(ptr_type->id == TypeTableEntryIdPointer);
8311
8312 TypeTableEntry *array_type = actual_type->data.pointer.child_type;
8313
8314 if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
8315 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, array_type->data.array.child_type,
8316 source_node, false).id == ConstCastResultIdOk)
8317 {
8318 return ImplicitCastMatchResultYes;
8319 }
8320 }
8321
8322 // implicit [N]T to &const []const T
8323 if (wanted_type->id == TypeTableEntryIdPointer &&
8324 wanted_type->data.pointer.is_const &&
8325 wanted_type->data.pointer.ptr_len == PtrLenSingle &&
8326 is_slice(wanted_type->data.pointer.child_type) &&
8327 actual_type->id == TypeTableEntryIdArray)
8328 {
8329 TypeTableEntry *ptr_type =
8330 wanted_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
8331 assert(ptr_type->id == TypeTableEntryIdPointer);
8332 if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
8333 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type,
8334 actual_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
8335 {
8336 return ImplicitCastMatchResultYes;
8337 }
8338 }
8339
8340 // implicit *[N]T to [*]T
8341 if (wanted_type->id == TypeTableEntryIdPointer &&
8342 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
8343 actual_type->id == TypeTableEntryIdPointer &&
8344 actual_type->data.pointer.ptr_len == PtrLenSingle &&
8345 actual_type->data.pointer.child_type->id == TypeTableEntryIdArray &&
8346 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8347 actual_type->data.pointer.child_type->data.array.child_type, source_node,
8348 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
8349 {
8350 return ImplicitCastMatchResultYes;
8351 }
8352
8353 // implicit *[N]T to []T
8354 if (is_slice(wanted_type) &&
8355 actual_type->id == TypeTableEntryIdPointer &&
8356 actual_type->data.pointer.ptr_len == PtrLenSingle &&
8357 actual_type->data.pointer.child_type->id == TypeTableEntryIdArray)
8358 {
8359 TypeTableEntry *slice_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
8360 assert(slice_ptr_type->id == TypeTableEntryIdPointer);
8361 if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
8362 actual_type->data.pointer.child_type->data.array.child_type, source_node,
8363 !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
8364 {
8365 return ImplicitCastMatchResultYes;
8366 }
8367 }
8368
8369 // implicit [N]T to ?[]const T
8370 if (wanted_type->id == TypeTableEntryIdOptional &&
8371 is_slice(wanted_type->data.maybe.child_type) &&
8372 actual_type->id == TypeTableEntryIdArray)
8373 {
8374 TypeTableEntry *ptr_type =
8375 wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry;
8376 assert(ptr_type->id == TypeTableEntryIdPointer);
8377 if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
8378 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type,
8379 actual_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
8380 {
8381 return ImplicitCastMatchResultYes;
8382 }
8383 }
8384
8385
8386 // implicit number literal to typed number
8387 // implicit number literal to &const integer
8388 if (actual_type->id == TypeTableEntryIdComptimeFloat ||
8389 actual_type->id == TypeTableEntryIdComptimeInt)
8390 {
8391 if (wanted_type->id == TypeTableEntryIdPointer &&
8392 wanted_type->data.pointer.ptr_len == PtrLenSingle &&
8393 wanted_type->data.pointer.is_const)
8394 {
8395 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.pointer.child_type, false)) {
8396 return ImplicitCastMatchResultYes;
8397 } else {
8398 return ImplicitCastMatchResultReportedError;
8399 }
8400 } else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, false)) {
8401 return ImplicitCastMatchResultYes;
8402 } else {
8403 return ImplicitCastMatchResultReportedError;
8404 }
8405 }
8406
8407 // implicit typed number to integer or float literal.
8408 // works when the number is known
8409 if (value->value.special == ConstValSpecialStatic) {
8410 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdComptimeInt) {
8411 return ImplicitCastMatchResultYes;
8412 } else if (actual_type->id == TypeTableEntryIdFloat && wanted_type->id == TypeTableEntryIdComptimeFloat) {
8413 return ImplicitCastMatchResultYes;
8414 }
8415 }
8416
8417 // implicit union to its enum tag type
8418 if (wanted_type->id == TypeTableEntryIdEnum && actual_type->id == TypeTableEntryIdUnion &&
8419 (actual_type->data.unionation.decl_node->data.container_decl.auto_enum ||
8420 actual_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
8421 {
8422 type_ensure_zero_bits_known(ira->codegen, actual_type);
8423 if (actual_type->data.unionation.tag_type == wanted_type) {
8424 return ImplicitCastMatchResultYes;
8425 }
8426 }
8427
8428 // implicit enum to union which has the enum as the tag type
8429 if (wanted_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&
8430 (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
8431 wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
8432 {
8433 type_ensure_zero_bits_known(ira->codegen, wanted_type);
8434 if (wanted_type->data.unionation.tag_type == actual_type) {
8435 return ImplicitCastMatchResultYes;
8436 }
8437 }
8438
8439 // implicit enum to &const union which has the enum as the tag type
8440 if (actual_type->id == TypeTableEntryIdEnum &&
8441 wanted_type->id == TypeTableEntryIdPointer &&
8442 wanted_type->data.pointer.ptr_len == PtrLenSingle)
8443 {
8444 TypeTableEntry *union_type = wanted_type->data.pointer.child_type;
8445 if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
8446 union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
8447 {
8448 type_ensure_zero_bits_known(ira->codegen, union_type);
8449 if (union_type->data.unionation.tag_type == actual_type) {
8450 return ImplicitCastMatchResultYes;
8451 }
8452 }
8453 }
8454
8455 // implicit T to *T where T is zero bits
8456 if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
8457 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8458 actual_type, source_node, false).id == ConstCastResultIdOk)
8459 {
8460 type_ensure_zero_bits_known(ira->codegen, actual_type);
8461 if (!type_has_bits(actual_type)) {
8462 return ImplicitCastMatchResultYes;
8463 }
8464 }
8465
8466 // implicit undefined literal to anything
8467 if (actual_type->id == TypeTableEntryIdUndefined) {
8468 return ImplicitCastMatchResultYes;
8469 }
8470
8471 // implicitly take a const pointer to something
8472 if (!type_requires_comptime(actual_type)) {
8473 TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true);
8474 if (wanted_type->id == TypeTableEntryIdPointer &&
8475 wanted_type->data.pointer.ptr_len == PtrLenSingle &&
8476 types_match_const_cast_only(ira, wanted_type, const_ptr_actual,
8477 source_node, false).id == ConstCastResultIdOk)
8478 {
8479 return ImplicitCastMatchResultYes;
8480 }
8481 }
8482
8483 return ImplicitCastMatchResultNo;
8484}
8485
84868213static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *errors_count) {
84878214 size_t old_errors_count = *errors_count;
84888215 *errors_count = g->errors_by_index.length;
......@@ -10227,6 +9954,83 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
102279954 return result;
102289955}
102299956
9957static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCastOnly *cast_result,
9958 ErrorMsg *parent_msg)
9959{
9960 switch (cast_result->id) {
9961 case ConstCastResultIdOk:
9962 zig_unreachable();
9963 case ConstCastResultIdOptionalChild: {
9964 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
9965 buf_sprintf("optional type child '%s' cannot cast into optional type child '%s'",
9966 buf_ptr(&cast_result->data.optional->actual_child->name),
9967 buf_ptr(&cast_result->data.optional->wanted_child->name)));
9968 report_recursive_error(ira, source_node, &cast_result->data.optional->child, msg);
9969 break;
9970 }
9971 case ConstCastResultIdErrorUnionErrorSet: {
9972 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
9973 buf_sprintf("error set '%s' cannot cast into error set '%s'",
9974 buf_ptr(&cast_result->data.error_union_error_set->actual_err_set->name),
9975 buf_ptr(&cast_result->data.error_union_error_set->wanted_err_set->name)));
9976 report_recursive_error(ira, source_node, &cast_result->data.error_union_error_set->child, msg);
9977 break;
9978 }
9979 case ConstCastResultIdErrSet: {
9980 ZigList<ErrorTableEntry *> *missing_errors = &cast_result->data.error_set_mismatch->missing_errors;
9981 for (size_t i = 0; i < missing_errors->length; i += 1) {
9982 ErrorTableEntry *error_entry = missing_errors->at(i);
9983 add_error_note(ira->codegen, parent_msg, error_entry->decl_node,
9984 buf_sprintf("'error.%s' not a member of destination error set", buf_ptr(&error_entry->name)));
9985 }
9986 break;
9987 }
9988 case ConstCastResultIdErrSetGlobal: {
9989 add_error_note(ira->codegen, parent_msg, source_node,
9990 buf_sprintf("cannot cast global error set into smaller set"));
9991 break;
9992 }
9993 case ConstCastResultIdPointerChild: {
9994 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
9995 buf_sprintf("pointer type child '%s' cannot cast into pointer type child '%s'",
9996 buf_ptr(&cast_result->data.pointer_mismatch->actual_child->name),
9997 buf_ptr(&cast_result->data.pointer_mismatch->wanted_child->name)));
9998 report_recursive_error(ira, source_node, &cast_result->data.pointer_mismatch->child, msg);
9999 break;
10000 }
10001 case ConstCastResultIdSliceChild: {
10002 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
10003 buf_sprintf("slice type child '%s' cannot cast into slice type child '%s'",
10004 buf_ptr(&cast_result->data.slice_mismatch->actual_child->name),
10005 buf_ptr(&cast_result->data.slice_mismatch->wanted_child->name)));
10006 report_recursive_error(ira, source_node, &cast_result->data.slice_mismatch->child, msg);
10007 break;
10008 }
10009 case ConstCastResultIdErrorUnionPayload: {
10010 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
10011 buf_sprintf("error union payload '%s' cannot cast into error union payload '%s'",
10012 buf_ptr(&cast_result->data.error_union_payload->actual_payload->name),
10013 buf_ptr(&cast_result->data.error_union_payload->wanted_payload->name)));
10014 report_recursive_error(ira, source_node, &cast_result->data.error_union_payload->child, msg);
10015 break;
10016 }
10017 case ConstCastResultIdFnAlign: // TODO
10018 case ConstCastResultIdFnCC: // TODO
10019 case ConstCastResultIdFnVarArgs: // TODO
10020 case ConstCastResultIdFnIsGeneric: // TODO
10021 case ConstCastResultIdFnReturnType: // TODO
10022 case ConstCastResultIdFnArgCount: // TODO
10023 case ConstCastResultIdFnGenericArgCount: // TODO
10024 case ConstCastResultIdFnArg: // TODO
10025 case ConstCastResultIdFnArgNoAlias: // TODO
10026 case ConstCastResultIdType: // TODO
10027 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
10028 case ConstCastResultIdAsyncAllocatorType: // TODO
10029 case ConstCastResultIdNullWrapPtr: // TODO
10030 break;
10031 }
10032}
10033
1023010034static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
1023110035 TypeTableEntry *wanted_type, IrInstruction *value)
1023210036{
......@@ -10238,11 +10042,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1023810042 }
1023910043
1024010044 // perfect match or non-const to const
10241 if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false).id == ConstCastResultIdOk) {
10045 ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,
10046 source_node, false);
10047 if (const_cast_result.id == ConstCastResultIdOk) {
1024210048 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
1024310049 }
1024410050
10245 // explicit widening conversion
10051 // widening conversion
1024610052 if (wanted_type->id == TypeTableEntryIdInt &&
1024710053 actual_type->id == TypeTableEntryIdInt &&
1024810054 wanted_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
......@@ -10259,7 +10065,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1025910065 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
1026010066 }
1026110067
10262 // explicit float widening conversion
10068 // float widening conversion
1026310069 if (wanted_type->id == TypeTableEntryIdFloat &&
1026410070 actual_type->id == TypeTableEntryIdFloat &&
1026510071 wanted_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
......@@ -10268,7 +10074,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1026810074 }
1026910075
1027010076
10271 // explicit cast from [N]T to []const T
10077 // cast from [N]T to []const T
1027210078 if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) {
1027310079 TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
1027410080 assert(ptr_type->id == TypeTableEntryIdPointer);
......@@ -10280,7 +10086,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1028010086 }
1028110087 }
1028210088
10283 // explicit cast from &const [N]T to []const T
10089 // cast from &const [N]T to []const T
1028410090 if (is_slice(wanted_type) &&
1028510091 actual_type->id == TypeTableEntryIdPointer &&
1028610092 actual_type->data.pointer.is_const &&
......@@ -10299,7 +10105,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1029910105 }
1030010106 }
1030110107
10302 // explicit cast from [N]T to &const []const T
10108 // cast from [N]T to &const []const T
1030310109 if (wanted_type->id == TypeTableEntryIdPointer &&
1030410110 wanted_type->data.pointer.is_const &&
1030510111 is_slice(wanted_type->data.pointer.child_type) &&
......@@ -10324,7 +10130,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1032410130 }
1032510131 }
1032610132
10327 // explicit cast from [N]T to ?[]const N
10133 // cast from [N]T to ?[]const N
1032810134 if (wanted_type->id == TypeTableEntryIdOptional &&
1032910135 is_slice(wanted_type->data.maybe.child_type) &&
1033010136 actual_type->id == TypeTableEntryIdArray)
......@@ -10348,7 +10154,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1034810154 }
1034910155 }
1035010156
10351 // explicit *[N]T to [*]T
10157 // *[N]T to [*]T
1035210158 if (wanted_type->id == TypeTableEntryIdPointer &&
1035310159 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
1035410160 actual_type->id == TypeTableEntryIdPointer &&
......@@ -10362,7 +10168,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1036210168 return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
1036310169 }
1036410170
10365 // explicit *[N]T to []T
10171 // *[N]T to []T
1036610172 if (is_slice(wanted_type) &&
1036710173 actual_type->id == TypeTableEntryIdPointer &&
1036810174 actual_type->data.pointer.ptr_len == PtrLenSingle &&
......@@ -10379,7 +10185,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1037910185 }
1038010186
1038110187
10382 // explicit cast from T to ?T
10188 // cast from T to ?T
1038310189 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
1038410190 if (wanted_type->id == TypeTableEntryIdOptional) {
1038510191 TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type;
......@@ -10411,14 +10217,14 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1041110217 }
1041210218 }
1041310219
10414 // explicit cast from null literal to maybe type
10220 // cast from null literal to maybe type
1041510221 if (wanted_type->id == TypeTableEntryIdOptional &&
1041610222 actual_type->id == TypeTableEntryIdNull)
1041710223 {
1041810224 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
1041910225 }
1042010226
10421 // explicit cast from child type of error type to error type
10227 // cast from child type of error type to error type
1042210228 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
1042310229 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
1042410230 source_node, false).id == ConstCastResultIdOk)
......@@ -10435,7 +10241,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1043510241 }
1043610242 }
1043710243
10438 // explicit cast from [N]T to E![]const T
10244 // cast from [N]T to E![]const T
1043910245 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
1044010246 is_slice(wanted_type->data.error_union.payload_type) &&
1044110247 actual_type->id == TypeTableEntryIdArray)
......@@ -10459,14 +10265,14 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1045910265 }
1046010266 }
1046110267
10462 // explicit cast from error set to error union type
10268 // cast from error set to error union type
1046310269 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
1046410270 actual_type->id == TypeTableEntryIdErrorSet)
1046510271 {
1046610272 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
1046710273 }
1046810274
10469 // explicit cast from T to E!?T
10275 // cast from T to E!?T
1047010276 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
1047110277 wanted_type->data.error_union.payload_type->id == TypeTableEntryIdOptional &&
1047210278 actual_type->id != TypeTableEntryIdOptional)
......@@ -10489,8 +10295,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1048910295 }
1049010296 }
1049110297
10492 // explicit cast from number literal to another type
10493 // explicit cast from number literal to *const integer
10298 // cast from number literal to another type
10299 // cast from number literal to *const integer
1049410300 if (actual_type->id == TypeTableEntryIdComptimeFloat ||
1049510301 actual_type->id == TypeTableEntryIdComptimeInt)
1049610302 {
......@@ -10540,7 +10346,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1054010346 }
1054110347 }
1054210348
10543 // explicit cast from typed number to integer or float literal.
10349 // cast from typed number to integer or float literal.
1054410350 // works when the number is known at compile time
1054510351 if (instr_is_comptime(value) &&
1054610352 ((actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdComptimeInt) ||
......@@ -10549,7 +10355,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1054910355 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
1055010356 }
1055110357
10552 // explicit cast from union to the enum type of the union
10358 // cast from union to the enum type of the union
1055310359 if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {
1055410360 type_ensure_zero_bits_known(ira->codegen, actual_type);
1055510361 if (type_is_invalid(actual_type))
......@@ -10560,7 +10366,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1056010366 }
1056110367 }
1056210368
10563 // explicit enum to union which has the enum as the tag type
10369 // enum to union which has the enum as the tag type
1056410370 if (wanted_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&
1056510371 (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
1056610372 wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
......@@ -10571,7 +10377,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1057110377 }
1057210378 }
1057310379
10574 // explicit enum to &const union which has the enum as the tag type
10380 // enum to &const union which has the enum as the tag type
1057510381 if (actual_type->id == TypeTableEntryIdEnum && wanted_type->id == TypeTableEntryIdPointer) {
1057610382 TypeTableEntry *union_type = wanted_type->data.pointer.child_type;
1057710383 if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
......@@ -10592,7 +10398,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1059210398 }
1059310399 }
1059410400
10595 // explicit cast from *T to *[1]T
10401 // cast from *T to *[1]T
1059610402 if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
1059710403 actual_type->id == TypeTableEntryIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle)
1059810404 {
......@@ -10616,7 +10422,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1061610422 }
1061710423 }
1061810424
10619 // explicit cast from T to *T where T is zero bits
10425 // cast from T to *T where T is zero bits
1062010426 if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
1062110427 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
1062210428 actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
......@@ -10631,12 +10437,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1063110437 }
1063210438
1063310439
10634 // explicit cast from undefined to anything
10440 // cast from undefined to anything
1063510441 if (actual_type->id == TypeTableEntryIdUndefined) {
1063610442 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
1063710443 }
1063810444
10639 // explicit cast from something to const pointer of it
10445 // cast from something to const pointer of it
1064010446 if (!type_requires_comptime(actual_type)) {
1064110447 TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true);
1064210448 if (types_match_const_cast_only(ira, wanted_type, const_ptr_actual, source_node, false).id == ConstCastResultIdOk) {
......@@ -10644,10 +10450,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1064410450 }
1064510451 }
1064610452
10647 ir_add_error_node(ira, source_instr->source_node,
10648 buf_sprintf("invalid cast from type '%s' to '%s'",
10649 buf_ptr(&actual_type->name),
10650 buf_ptr(&wanted_type->name)));
10453 ErrorMsg *parent_msg = ir_add_error_node(ira, source_instr->source_node,
10454 buf_sprintf("expected type '%s', found '%s'",
10455 buf_ptr(&wanted_type->name),
10456 buf_ptr(&actual_type->name)));
10457 report_recursive_error(ira, source_instr->source_node, &const_cast_result, parent_msg);
1065110458 return ira->codegen->invalid_instruction;
1065210459}
1065310460
......@@ -10664,22 +10471,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
1066410471 if (value->value.type->id == TypeTableEntryIdUnreachable)
1066510472 return value;
1066610473
10667 ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->value.type, value);
10668 switch (result) {
10669 case ImplicitCastMatchResultNo:
10670 ir_add_error(ira, value,
10671 buf_sprintf("expected type '%s', found '%s'",
10672 buf_ptr(&expected_type->name),
10673 buf_ptr(&value->value.type->name)));
10674 return ira->codegen->invalid_instruction;
10675
10676 case ImplicitCastMatchResultYes:
10677 return ir_analyze_cast(ira, value, expected_type, value);
10678 case ImplicitCastMatchResultReportedError:
10679 return ira->codegen->invalid_instruction;
10680 }
10681
10682 zig_unreachable();
10474 return ir_analyze_cast(ira, value, expected_type, value);
1068310475}
1068410476
1068510477static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
test/compile_errors.zig+11-8
......@@ -100,7 +100,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
100100 \\ var rule_set = try Foo.init();
101101 \\}
102102 ,
103 ".tmp_source.zig:2:13: error: invalid cast from type 'type' to 'i32'",
103 ".tmp_source.zig:2:13: error: expected type 'i32', found 'type'",
104104 );
105105
106106 cases.add(
......@@ -122,7 +122,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
122122 );
123123
124124 cases.add(
125 "invalid deref on switch target",
125 "nested error set mismatch",
126126 \\const NextError = error{NextError};
127127 \\const OtherError = error{OutOfMemory};
128128 \\
......@@ -134,7 +134,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
134134 \\ return null;
135135 \\}
136136 ,
137 ".tmp_source.zig:5:34: error: expected 'NextError!i32', found 'OtherError!i32'",
137 ".tmp_source.zig:5:34: error: expected type '?NextError!i32', found '?OtherError!i32'",
138 ".tmp_source.zig:5:34: note: optional type child 'OtherError!i32' cannot cast into optional type child 'NextError!i32'",
139 ".tmp_source.zig:5:34: note: error set 'OtherError' cannot cast into error set 'NextError'",
138140 ".tmp_source.zig:2:26: note: 'error.OutOfMemory' not a member of destination error set",
139141 );
140142
......@@ -437,8 +439,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
437439 \\ return error.B;
438440 \\}
439441 ,
440 ".tmp_source.zig:3:35: error: expected 'SmallErrorSet!i32', found 'error!i32'",
441 ".tmp_source.zig:3:35: note: unable to cast global error set into smaller set",
442 ".tmp_source.zig:3:35: error: expected type 'SmallErrorSet!i32', found 'error!i32'",
443 ".tmp_source.zig:3:35: note: error set 'error' cannot cast into error set 'SmallErrorSet'",
444 ".tmp_source.zig:3:35: note: cannot cast global error set into smaller set",
442445 );
443446
444447 cases.add(
......@@ -451,8 +454,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
451454 \\ return error.B;
452455 \\}
453456 ,
454 ".tmp_source.zig:3:31: error: expected 'SmallErrorSet', found 'error'",
455 ".tmp_source.zig:3:31: note: unable to cast global error set into smaller set",
457 ".tmp_source.zig:3:31: error: expected type 'SmallErrorSet', found 'error'",
458 ".tmp_source.zig:3:31: note: cannot cast global error set into smaller set",
456459 );
457460
458461 cases.add(
......@@ -478,7 +481,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
478481 \\ var x: Set2 = set1;
479482 \\}
480483 ,
481 ".tmp_source.zig:7:19: error: expected 'Set2', found 'Set1'",
484 ".tmp_source.zig:7:19: error: expected type 'Set2', found 'Set1'",
482485 ".tmp_source.zig:1:23: note: 'error.B' not a member of destination error set",
483486 );
484487