authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-24 18:56:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-24 22:35:37-07:00
log9c95f38a7c1defc7f63a4815bfc2d76a5f9f83f6
tree3182a24f22da9da86b56d8894b4bd603e89e10e3
parentf1f28af1880a79bb2d7210d3a704c78698f0b45b

stage1: remove incorrect compile error for var redeclaration

Locals are not allowed to shadow declarations, but declarations are allowed to shadow each other, as long as there are no ambiguous references. closes #678

6 files changed, 67 insertions(+), 83 deletions(-)

src/stage1/analyze.cpp+4-39
...@@ -4171,46 +4171,11 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -4171,46 +4171,11 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
4171 } else {4171 } else {
4172 variable_entry->align_bytes = get_abi_alignment(g, var_type);4172 variable_entry->align_bytes = get_abi_alignment(g, var_type);
41734173
4174 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);4174 ZigType *type;
4175 if (existing_var && !existing_var->shadowable) {4175 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
4176 if (existing_var->var_type == nullptr || !type_is_invalid(existing_var->var_type)) {4176 add_node_error(g, source_node,
4177 ErrorMsg *msg = add_node_error(g, source_node,4177 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
4178 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
4179 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration here"));
4180 }
4181 variable_entry->var_type = g->builtin_types.entry_invalid;4178 variable_entry->var_type = g->builtin_types.entry_invalid;
4182 } else {
4183 ZigType *type;
4184 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
4185 add_node_error(g, source_node,
4186 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
4187 variable_entry->var_type = g->builtin_types.entry_invalid;
4188 } else {
4189 Scope *search_scope = nullptr;
4190 if (src_tld == nullptr) {
4191 search_scope = parent_scope;
4192 } else if (src_tld->parent_scope != nullptr && src_tld->parent_scope->parent != nullptr) {
4193 search_scope = src_tld->parent_scope->parent;
4194 }
4195 if (search_scope != nullptr) {
4196 Tld *tld = find_decl(g, search_scope, name);
4197 if (tld != nullptr && tld != src_tld) {
4198 bool want_err_msg = true;
4199 if (tld->id == TldIdVar) {
4200 ZigVar *var = reinterpret_cast<TldVar *>(tld)->var;
4201 if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) {
4202 want_err_msg = false;
4203 }
4204 }
4205 if (want_err_msg) {
4206 ErrorMsg *msg = add_node_error(g, source_node,
4207 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
4208 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition here"));
4209 }
4210 variable_entry->var_type = g->builtin_types.entry_invalid;
4211 }
4212 }
4213 }
4214 }4179 }
4215 }4180 }
42164181
src/stage1/astgen.cpp+25-18
...@@ -3200,23 +3200,6 @@ ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope,...@@ -3200,23 +3200,6 @@ ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope,
3200 add_node_error(codegen, node,3200 add_node_error(codegen, node,
3201 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));3201 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3202 variable_entry->var_type = codegen->builtin_types.entry_invalid;3202 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3203 } else {
3204 Tld *tld = find_decl(codegen, parent_scope, name);
3205 if (tld != nullptr) {
3206 bool want_err_msg = true;
3207 if (tld->id == TldIdVar) {
3208 ZigVar *var = reinterpret_cast<TldVar *>(tld)->var;
3209 if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) {
3210 want_err_msg = false;
3211 }
3212 }
3213 if (want_err_msg) {
3214 ErrorMsg *msg = add_node_error(codegen, node,
3215 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3216 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition here"));
3217 }
3218 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3219 }
3220 }3203 }
3221 }3204 }
3222 }3205 }
...@@ -3875,7 +3858,31 @@ static Stage1ZirInst *astgen_identifier(Stage1AstGen *ag, Scope *scope, AstNode...@@ -3875,7 +3858,31 @@ static Stage1ZirInst *astgen_identifier(Stage1AstGen *ag, Scope *scope, AstNode
3875 }3858 }
3876 }3859 }
38773860
3878 Tld *tld = find_decl(ag->codegen, scope, variable_name);3861 Tld *tld = nullptr;
3862 {
3863 Scope *s = scope;
3864 while (s) {
3865 if (s->id == ScopeIdDecls) {
3866 ScopeDecls *decls_scope = (ScopeDecls *)s;
3867
3868 Tld *result = find_container_decl(ag->codegen, decls_scope, variable_name);
3869 if (result != nullptr) {
3870 if (tld != nullptr && tld != result) {
3871 ErrorMsg *msg = add_node_error(ag->codegen, node,
3872 buf_sprintf("ambiguous reference"));
3873 add_error_note(ag->codegen, msg, tld->source_node,
3874 buf_sprintf("declared here"));
3875 add_error_note(ag->codegen, msg, result->source_node,
3876 buf_sprintf("also declared here"));
3877 return ag->codegen->invalid_inst_src;
3878 }
3879 tld = result;
3880 }
3881 }
3882 s = s->parent;
3883 }
3884 }
3885
3879 if (tld) {3886 if (tld) {
3880 Stage1ZirInst *decl_ref = ir_build_decl_ref(ag, scope, node, tld, lval);3887 Stage1ZirInst *decl_ref = ir_build_decl_ref(ag, scope, node, tld, lval);
3881 if (lval == LValPtr || lval == LValAssign) {3888 if (lval == LValPtr || lval == LValAssign) {
test/behavior/error.zig+6-6
...@@ -412,19 +412,19 @@ test "function pointer with return type that is error union with payload which i...@@ -412,19 +412,19 @@ test "function pointer with return type that is error union with payload which i
412test "return result loc as peer result loc in inferred error set function" {412test "return result loc as peer result loc in inferred error set function" {
413 const S = struct {413 const S = struct {
414 fn doTheTest() !void {414 fn doTheTest() !void {
415 if (foo(2)) |x| {415 if (quux(2)) |x| {
416 try expect(x.Two);416 try expect(x.Two);
417 } else |e| switch (e) {417 } else |e| switch (e) {
418 error.Whatever => @panic("fail"),418 error.Whatever => @panic("fail"),
419 }419 }
420 try expectError(error.Whatever, foo(99));420 try expectError(error.Whatever, quux(99));
421 }421 }
422 const FormValue = union(enum) {422 const FormValue = union(enum) {
423 One: void,423 One: void,
424 Two: bool,424 Two: bool,
425 };425 };
426426
427 fn foo(id: u64) !FormValue {427 fn quux(id: u64) !FormValue {
428 return switch (id) {428 return switch (id) {
429 2 => FormValue{ .Two = true },429 2 => FormValue{ .Two = true },
430 1 => FormValue{ .One = {} },430 1 => FormValue{ .One = {} },
...@@ -452,11 +452,11 @@ test "error payload type is correctly resolved" {...@@ -452,11 +452,11 @@ test "error payload type is correctly resolved" {
452452
453test "error union comptime caching" {453test "error union comptime caching" {
454 const S = struct {454 const S = struct {
455 fn foo(comptime arg: anytype) void {455 fn quux(comptime arg: anytype) void {
456 arg catch {};456 arg catch {};
457 }457 }
458 };458 };
459459
460 S.foo(@as(anyerror!void, {}));460 S.quux(@as(anyerror!void, {}));
461 S.foo(@as(anyerror!void, {}));461 S.quux(@as(anyerror!void, {}));
462}462}
test/behavior/misc.zig+17
...@@ -505,3 +505,20 @@ test "lazy typeInfo value as generic parameter" {...@@ -505,3 +505,20 @@ test "lazy typeInfo value as generic parameter" {
505 };505 };
506 S.foo(@typeInfo(@TypeOf(.{})));506 S.foo(@typeInfo(@TypeOf(.{})));
507}507}
508
509fn A() type {
510 return struct {
511 b: B(),
512
513 const Self = @This();
514
515 fn B() type {
516 return struct {
517 const Self = @This();
518 };
519 }
520 };
521}
522test "non-ambiguous reference of shadowed decls" {
523 try expect(A().B().Self != A().Self);
524}
test/behavior/struct.zig+2-2
...@@ -162,14 +162,14 @@ const MemberFnRand = struct {...@@ -162,14 +162,14 @@ const MemberFnRand = struct {
162};162};
163163
164test "return struct byval from function" {164test "return struct byval from function" {
165 const bar = makeBar(1234, 5678);165 const bar = makeBar2(1234, 5678);
166 try expect(bar.y == 5678);166 try expect(bar.y == 5678);
167}167}
168const Bar = struct {168const Bar = struct {
169 x: i32,169 x: i32,
170 y: i32,170 y: i32,
171};171};
172fn makeBar(x: i32, y: i32) Bar {172fn makeBar2(x: i32, y: i32) Bar {
173 return Bar{173 return Bar{
174 .x = x,174 .x = x,
175 .y = y,175 .y = y,
test/compile_errors.zig+13-18
...@@ -6969,29 +6969,24 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -6969,29 +6969,24 @@ pub fn addCases(ctx: *TestContext) !void {
6969 "tmp.zig:2:30: error: cannot set section of local variable 'foo'",6969 "tmp.zig:2:30: error: cannot set section of local variable 'foo'",
6970 });6970 });
69716971
6972 ctx.objErrStage1("inner struct member shadowing outer struct member",6972 ctx.objErrStage1("ambiguous decl reference",
6973 \\fn A() type {6973 \\fn foo() void {}
6974 \\ return struct {6974 \\fn bar() void {
6975 \\ b: B(),6975 \\ const S = struct {
6976 \\6976 \\ fn baz() void {
6977 \\ const Self = @This();6977 \\ foo();
6978 \\
6979 \\ fn B() type {
6980 \\ return struct {
6981 \\ const Self = @This();
6982 \\ };
6983 \\ }6978 \\ }
6979 \\ fn foo() void {}
6984 \\ };6980 \\ };
6981 \\ S.baz();
6985 \\}6982 \\}
6986 \\comptime {6983 \\export fn entry() void {
6987 \\ assert(A().B().Self != A().Self);6984 \\ bar();
6988 \\}
6989 \\fn assert(ok: bool) void {
6990 \\ if (!ok) unreachable;
6991 \\}6985 \\}
6992 , &[_][]const u8{6986 , &[_][]const u8{
6993 "tmp.zig:9:17: error: redefinition of 'Self'",6987 "tmp.zig:5:13: error: ambiguous reference",
6994 "tmp.zig:5:9: note: previous definition here",6988 "tmp.zig:7:9: note: declared here",
6989 "tmp.zig:1:1: note: also declared here",
6995 });6990 });
69966991
6997 ctx.objErrStage1("while expected bool, got optional",6992 ctx.objErrStage1("while expected bool, got optional",