Commit 0940d46c01

Andrew Kelley <superjoe30@gmail.com>
2017-05-03 22:13:22
add compile error for shadowing variable
closes #360
1 parent 6756c27
Changed files (2)
src/analyze.cpp
@@ -2289,13 +2289,21 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent
                 add_node_error(g, source_node,
                         buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
                 variable_entry->value->type = g->builtin_types.entry_invalid;
-            } else if (src_tld == nullptr) {
-                Tld *tld = find_decl(g, parent_scope, name);
-                if (tld) {
-                    ErrorMsg *msg = add_node_error(g, source_node,
-                            buf_sprintf("redefinition of '%s'", buf_ptr(name)));
-                    add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
-                    variable_entry->value->type = g->builtin_types.entry_invalid;
+            } else {
+                Scope *search_scope = nullptr;
+                if (src_tld == nullptr) {
+                    search_scope = parent_scope;
+                } else if (src_tld->parent_scope != nullptr && src_tld->parent_scope->parent != nullptr) {
+                    search_scope = src_tld->parent_scope->parent;
+                }
+                if (search_scope != nullptr) {
+                    Tld *tld = find_decl(g, search_scope, name);
+                    if (tld != nullptr) {
+                        ErrorMsg *msg = add_node_error(g, source_node,
+                                buf_sprintf("redefinition of '%s'", buf_ptr(name)));
+                        add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
+                        variable_entry->value->type = g->builtin_types.entry_invalid;
+                    }
                 }
             }
         }
test/compile_errors.zig
@@ -1630,4 +1630,28 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
         \\}
     ,
         ".tmp_source.zig:4:12: error: function returns address of local variable");
+
+    cases.add("inner struct member shadowing outer struct member",
+        \\fn A() -> type {
+        \\    struct {
+        \\        b: B(),
+        \\
+        \\        const Self = this;
+        \\
+        \\        fn B() -> type {
+        \\            struct {
+        \\                const Self = this;
+        \\            }
+        \\        }
+        \\    }
+        \\}
+        \\comptime {
+        \\    assert(A().B().Self != A().Self);
+        \\}
+        \\fn assert(ok: bool) {
+        \\    if (!ok) unreachable;
+        \\}
+    ,
+        ".tmp_source.zig:9:17: error: redefinition of 'Self'",
+        ".tmp_source.zig:5:9: note: previous definition is here");
 }