Commit b91eaba38c

LemonBoy <thatlemon@gmail.com>
2020-01-02 23:56:14
Correct evaluation of optional type alignment
The lazy logic was too oversimplified and produced a different result than the one computed later causing all kinds of problems. Closes #4013
1 parent 3f19bc5
Changed files (4)
src/analyze.cpp
@@ -1331,7 +1331,7 @@ start_over:
     zig_unreachable();
 }
 
-Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_align) {
+Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align) {
     Error err;
     if (type_val->special != ConstValSpecialLazy) {
         assert(type_val->special == ConstValSpecialStatic);
@@ -1356,19 +1356,21 @@ Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_a
             *abi_align = g->builtin_types.entry_usize->abi_align;
             return ErrorNone;
         case LazyValueIdOptType: {
-            LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
-            return type_val_resolve_abi_align(g, lazy_opt_type->payload_type->value, abi_align);
+            if ((err = ir_resolve_lazy(g, nullptr, type_val)))
+                return err;
+
+            return type_val_resolve_abi_align(g, source_node, type_val, abi_align);
         }
         case LazyValueIdArrayType: {
             LazyValueArrayType *lazy_array_type =
                 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
-            return type_val_resolve_abi_align(g, lazy_array_type->elem_type->value, abi_align);
+            return type_val_resolve_abi_align(g, source_node, lazy_array_type->elem_type->value, abi_align);
         }
         case LazyValueIdErrUnionType: {
             LazyValueErrUnionType *lazy_err_union_type =
                 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
             uint32_t payload_abi_align;
-            if ((err = type_val_resolve_abi_align(g, lazy_err_union_type->payload_type->value,
+            if ((err = type_val_resolve_abi_align(g, source_node, lazy_err_union_type->payload_type->value,
                             &payload_abi_align)))
             {
                 return err;
@@ -2335,7 +2337,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
             }
             field->align = field->type_entry->abi_align;
         } else {
-            if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
+            if ((err = type_val_resolve_abi_align(g, field->decl_node, field->type_val, &field->align))) {
                 if (g->trace_err != nullptr) {
                     g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
                         buf_create_from_str("while checking this field"));
@@ -2912,7 +2914,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
         } else if (packed) {
             field->align = 1;
         } else {
-            if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
+            if ((err = type_val_resolve_abi_align(g, field->decl_node, field->type_val, &field->align))) {
                 if (g->trace_err != nullptr) {
                     g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
                         buf_create_from_str("while checking this field"));
src/analyze.hpp
@@ -260,7 +260,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *
 void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
 bool fn_is_async(ZigFn *fn);
 
-Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_align);
+Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align);
 Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val,
         size_t *abi_size, size_t *size_in_bits);
 Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type,
src/ir.cpp
@@ -29200,8 +29200,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
             }
 
             uint32_t align_in_bytes;
-            if ((err = type_val_resolve_abi_align(ira->codegen, lazy_align_of->target_type->value,
-                            &align_in_bytes)))
+            if ((err = type_val_resolve_abi_align(ira->codegen, source_node,
+                    lazy_align_of->target_type->value, &align_in_bytes)))
             {
                 return err;
             }
test/stage1/behavior/optional.zig
@@ -145,3 +145,11 @@ test "coerce an anon struct literal to optional struct" {
     S.doTheTest();
     comptime S.doTheTest();
 }
+
+test "optional with void type" {
+    const Foo = struct {
+        x: ?void,
+    };
+    var x = Foo{ .x = null };
+    expect(x.x == null);
+}