Commit 08a7ce7dd5

Andrew Kelley <superjoe30@gmail.com>
2015-12-24 21:47:07
add error for missing or duplicate field in struct value expr
1 parent 8915883
Changed files (2)
src/analyze.cpp
@@ -1309,7 +1309,11 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
     node->codegen_node->data.struct_val_expr_node.source_node = node;
     context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node);
 
-    for (int i = 0; i < struct_val_expr->fields.length; i += 1) {
+    int expr_field_count = struct_val_expr->fields.length;
+    int actual_field_count = type_entry->data.structure.field_count;
+
+    int *field_use_counts = allocate<int>(actual_field_count);
+    for (int i = 0; i < expr_field_count; i += 1) {
         AstNode *val_field_node = struct_val_expr->fields.at(i);
         int field_index;
         TypeStructField *type_field = find_struct_type_field(type_entry,
@@ -1317,7 +1321,14 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
 
         if (!type_field) {
             add_node_error(g, val_field_node,
-                buf_sprintf("type '%s' is not a struct", buf_ptr(&type_entry->name)));
+                buf_sprintf("no member named '%s' in '%s'",
+                    buf_ptr(&val_field_node->data.struct_val_field.name), buf_ptr(&type_entry->name)));
+            continue;
+        }
+
+        field_use_counts[field_index] += 1;
+        if (field_use_counts[field_index] > 1) {
+            add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
             continue;
         }
 
@@ -1328,6 +1339,13 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
                 val_field_node->data.struct_val_field.expr);
     }
 
+    for (int i = 0; i < actual_field_count; i += 1) {
+        if (field_use_counts[i] == 0) {
+            add_node_error(g, node,
+                buf_sprintf("missing field: '%s'", buf_ptr(type_entry->data.structure.fields[i].name)));
+        }
+    }
+
     return type_entry;
 }
 
test/run_tests.cpp
@@ -877,6 +877,36 @@ struct A { y : i32, }
 struct A { x : i32, }
 export fn f(a : A) {}
     )SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue struct parameters not yet supported on exported functions");
+
+    add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(
+struct A {
+    x : i32,
+    y : i32,
+    z : i32,
+}
+fn f() {
+    const a = A {
+        .z = 1,
+        .y = 2,
+        .x = 3,
+        .z = 4,
+    };
+}
+    )SOURCE", 1, ".tmp_source.zig:12:9: error: duplicate field");
+
+    add_compile_fail_case("missing field in struct value expression", R"SOURCE(
+struct A {
+    x : i32,
+    y : i32,
+    z : i32,
+}
+fn f() {
+    const a = A {
+        .z = 4,
+        .y = 2,
+    };
+}
+    )SOURCE", 1, ".tmp_source.zig:8:15: error: missing field: 'x'");
 }
 
 static void print_compiler_invocation(TestCase *test_case) {