Commit e2dc63644a

Andrew Kelley <andrew@ziglang.org>
2020-04-05 23:09:01
type_has_one_possible_value takes comptime struct fields into account
Before, type_has_one_possible_value would return false for the value `.{1}`. But actually, that type is a tuple with a single comptime field. Such a type, in fact, has one possible value. This plus the corresponding adjustment to get_the_one_possible_value solves #3878.
1 parent 6ef15fc
Changed files (2)
src
test
stage1
behavior
src/analyze.cpp
@@ -5769,6 +5769,10 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
             type_entry->one_possible_value = OnePossibleValueNo;
             for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
                 TypeStructField *field = type_entry->data.structure.fields[i];
+                if (field->is_comptime) {
+                    // If this field is comptime then the field can only be one possible value
+                    continue;
+                }
                 OnePossibleValue opv = (field->type_entry != nullptr) ?
                     type_has_one_possible_value(g, field->type_entry) :
                     type_val_resolve_has_one_possible_value(g, field->type_val);
@@ -5825,6 +5829,10 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
         result->data.x_struct.fields = alloc_const_vals_ptrs(g, field_count);
         for (size_t i = 0; i < field_count; i += 1) {
             TypeStructField *field = struct_type->data.structure.fields[i];
+            if (field->is_comptime) {
+                copy_const_val(g, result->data.x_struct.fields[i], field->init_val);
+                continue;
+            }
             ZigType *field_type = resolve_struct_field_type(g, field);
             assert(field_type != nullptr);
             result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
test/stage1/behavior/tuple.zig
@@ -36,7 +36,7 @@ test "tuple concatenation" {
             consume_tuple(.{} ++ .{}, 0);
             consume_tuple(.{0} ++ .{}, 1);
             consume_tuple(.{0} ++ .{1}, 2);
-            consume_tuple(.{0, 1, 2} ++ .{u8, 1, noreturn}, 6);
+            consume_tuple(.{ 0, 1, 2 } ++ .{ u8, 1, noreturn }, 6);
             consume_tuple(t2 ++ t1, 1);
             consume_tuple(t1 ++ t2, 1);
             consume_tuple(t2 ++ t2, 2);
@@ -54,3 +54,17 @@ test "tuple concatenation" {
     T.doTheTest();
     comptime T.doTheTest();
 }
+
+test "pass tuple to comptime var parameter" {
+    const S = struct {
+        fn Foo(comptime args: var) void {
+            expect(args[0] == 1);
+        }
+
+        fn doTheTest() void {
+            Foo(.{1});
+        }
+    };
+    S.doTheTest();
+    comptime S.doTheTest();
+}