authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-09-18 21:25:37+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-18 22:12:22-04:00
logf92d01c8a86b525c2caaf07497e16841905cea8c
treed75b73ef1734ea5b11cbdfe8ae400f7b4bc7604b
parent4fbf9f7f79c8e0df525f9932878995e6a6782ac4

stage1: Fix edge case in casting between optional types

Closes #6370

2 files changed, 28 insertions(+), 1 deletions(-)

src/ir.cpp+23-1
...@@ -63,6 +63,7 @@ enum ConstCastResultId {...@@ -63,6 +63,7 @@ enum ConstCastResultId {
63 ConstCastResultIdPointerChild,63 ConstCastResultIdPointerChild,
64 ConstCastResultIdSliceChild,64 ConstCastResultIdSliceChild,
65 ConstCastResultIdOptionalChild,65 ConstCastResultIdOptionalChild,
66 ConstCastResultIdOptionalShape,
66 ConstCastResultIdErrorUnionPayload,67 ConstCastResultIdErrorUnionPayload,
67 ConstCastResultIdErrorUnionErrorSet,68 ConstCastResultIdErrorUnionErrorSet,
68 ConstCastResultIdFnAlign,69 ConstCastResultIdFnAlign,
...@@ -11946,8 +11947,22 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -11946,8 +11947,22 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
11946 }11947 }
11947 }11948 }
1194811949
11949 // maybe11950 // optional types
11950 if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {11951 if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {
11952 // Consider the case where the wanted type is ??[*]T and the actual one
11953 // is ?[*]T, we cannot turn the former into the latter even though the
11954 // child types are compatible (?[*]T and [*]T are both represented as a
11955 // pointer). The extra level of indirection in ??[*]T means it's
11956 // represented as a regular, fat, optional type and, as a consequence,
11957 // has a different shape than the one of ?[*]T.
11958 if ((wanted_ptr_type != nullptr) != (actual_ptr_type != nullptr)) {
11959 // The use of type_mismatch is intentional
11960 result.id = ConstCastResultIdOptionalShape;
11961 result.data.type_mismatch = heap::c_allocator.allocate_nonzero<ConstCastTypeMismatch>(1);
11962 result.data.type_mismatch->wanted_type = wanted_type;
11963 result.data.type_mismatch->actual_type = actual_type;
11964 return result;
11965 }
11951 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,11966 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,
11952 actual_type->data.maybe.child_type, source_node, wanted_is_mutable);11967 actual_type->data.maybe.child_type, source_node, wanted_is_mutable);
11953 if (child.id == ConstCastResultIdInvalid)11968 if (child.id == ConstCastResultIdInvalid)
...@@ -14549,6 +14564,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -14549,6 +14564,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
14549 report_recursive_error(ira, source_node, &cast_result->data.optional->child, msg);14564 report_recursive_error(ira, source_node, &cast_result->data.optional->child, msg);
14550 break;14565 break;
14551 }14566 }
14567 case ConstCastResultIdOptionalShape: {
14568 add_error_note(ira->codegen, parent_msg, source_node,
14569 buf_sprintf("optional type child '%s' cannot cast into optional type '%s'",
14570 buf_ptr(&cast_result->data.type_mismatch->actual_type->name),
14571 buf_ptr(&cast_result->data.type_mismatch->wanted_type->name)));
14572 break;
14573 }
14552 case ConstCastResultIdErrorUnionErrorSet: {14574 case ConstCastResultIdErrorUnionErrorSet: {
14553 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,14575 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
14554 buf_sprintf("error set '%s' cannot cast into error set '%s'",14576 buf_sprintf("error set '%s' cannot cast into error set '%s'",
test/stage1/behavior/cast.zig+5
...@@ -849,3 +849,8 @@ test "comptime float casts" {...@@ -849,3 +849,8 @@ test "comptime float casts" {
849 expect(b == 2);849 expect(b == 2);
850 expect(@TypeOf(b) == comptime_int);850 expect(@TypeOf(b) == comptime_int);
851}851}
852
853test "cast from ?[*]T to ??[*]T" {
854 const a: ??[*]u8 = @as(?[*]u8, null);
855 expect(a != null and a.? == null);
856}