From 2962be81359a6806f66d220474abcb0b1cf7edf0 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Wed, 16 Sep 2020 03:29:38 -0600 Subject: stage1: fix @Type(.Union) not resolving its tag type Fixes https://github.com/ziglang/zig/issues/6339 --- src/analyze.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/analyze.cpp b/src/analyze.cpp index b53d263539..3ba4fd7928 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3155,30 +3155,29 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { tag_type->data.enumeration.fields_by_name.init(field_count); tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope; } else if (enum_type_node != nullptr) { - ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node); - if (type_is_invalid(enum_type)) { + tag_type = analyze_type_expr(g, scope, enum_type_node); + } else { + if (decl_node->type == NodeTypeContainerDecl) { + tag_type = nullptr; + } else { + tag_type = union_type->data.unionation.tag_type; + } + } + if (tag_type != nullptr) { + if (type_is_invalid(tag_type)) { union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } - if (enum_type->id != ZigTypeIdEnum) { + if (tag_type->id != ZigTypeIdEnum) { union_type->data.unionation.resolve_status = ResolveStatusInvalid; - add_node_error(g, enum_type_node, - buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); + add_node_error(g, enum_type_node != nullptr ? enum_type_node : decl_node, + buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&tag_type->name))); return ErrorSemanticAnalyzeFail; } - if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) { + if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) { assert(g->errors.length != 0); return err; } - tag_type = enum_type; - } else { - if (decl_node->type == NodeTypeContainerDecl) { - tag_type = nullptr; - } else { - tag_type = union_type->data.unionation.tag_type; - } - } - if (tag_type != nullptr) { covered_enum_fields = heap::c_allocator.allocate(tag_type->data.enumeration.src_field_count); } union_type->data.unionation.tag_type = tag_type; -- cgit v1.2.3 From f92d01c8a86b525c2caaf07497e16841905cea8c Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 18 Sep 2020 21:25:37 +0200 Subject: stage1: Fix edge case in casting between optional types Closes #6370 --- src/ir.cpp | 24 +++++++++++++++++++++++- test/stage1/behavior/cast.zig | 5 +++++ 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 6cb5d8bc2d..7d446c82a0 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -63,6 +63,7 @@ enum ConstCastResultId { ConstCastResultIdPointerChild, ConstCastResultIdSliceChild, ConstCastResultIdOptionalChild, + ConstCastResultIdOptionalShape, ConstCastResultIdErrorUnionPayload, ConstCastResultIdErrorUnionErrorSet, ConstCastResultIdFnAlign, @@ -11946,8 +11947,22 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted } } - // maybe + // optional types if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) { + // Consider the case where the wanted type is ??[*]T and the actual one + // is ?[*]T, we cannot turn the former into the latter even though the + // child types are compatible (?[*]T and [*]T are both represented as a + // pointer). The extra level of indirection in ??[*]T means it's + // represented as a regular, fat, optional type and, as a consequence, + // has a different shape than the one of ?[*]T. + if ((wanted_ptr_type != nullptr) != (actual_ptr_type != nullptr)) { + // The use of type_mismatch is intentional + result.id = ConstCastResultIdOptionalShape; + result.data.type_mismatch = heap::c_allocator.allocate_nonzero(1); + result.data.type_mismatch->wanted_type = wanted_type; + result.data.type_mismatch->actual_type = actual_type; + return result; + } ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type, actual_type->data.maybe.child_type, source_node, wanted_is_mutable); if (child.id == ConstCastResultIdInvalid) @@ -14549,6 +14564,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa report_recursive_error(ira, source_node, &cast_result->data.optional->child, msg); break; } + case ConstCastResultIdOptionalShape: { + add_error_note(ira->codegen, parent_msg, source_node, + buf_sprintf("optional type child '%s' cannot cast into optional type '%s'", + buf_ptr(&cast_result->data.type_mismatch->actual_type->name), + buf_ptr(&cast_result->data.type_mismatch->wanted_type->name))); + break; + } case ConstCastResultIdErrorUnionErrorSet: { ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("error set '%s' cannot cast into error set '%s'", diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index 4b678cd2db..ce0d16d1a0 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -849,3 +849,8 @@ test "comptime float casts" { expect(b == 2); expect(@TypeOf(b) == comptime_int); } + +test "cast from ?[*]T to ??[*]T" { + const a: ??[*]u8 = @as(?[*]u8, null); + expect(a != null and a.? == null); +} -- cgit v1.2.3