stage2: compile error for ambiguous decl refrences

std: fix compile errors from this change. This is a stage1 bug.
This commit is contained in:
jacob gw 2021-05-27 21:29:14 -04:00 committed by Andrew Kelley
parent 143688e266
commit b57ac48773
3 changed files with 72 additions and 9 deletions

View File

@ -2564,8 +2564,8 @@ fn rowSize(tree: ast.Tree, exprs: []const ast.Node.Index, rtoken: ast.TokenIndex
fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
return struct {
const Self = @This();
pub const Error = UnderlyingWriter.Error;
pub const Writer = std.io.Writer(*Self, Error, write);
pub const WriteError = UnderlyingWriter.Error;
pub const Writer = std.io.Writer(*Self, WriteError, write);
underlying_writer: UnderlyingWriter,
@ -2591,7 +2591,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
return .{ .context = self };
}
pub fn write(self: *Self, bytes: []const u8) Error!usize {
pub fn write(self: *Self, bytes: []const u8) WriteError!usize {
if (bytes.len == 0)
return @as(usize, 0);
@ -2614,7 +2614,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
self.indent_delta = new_indent_delta;
}
fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
fn writeNoIndent(self: *Self, bytes: []const u8) WriteError!usize {
if (bytes.len == 0)
return @as(usize, 0);
@ -2624,7 +2624,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
return bytes.len;
}
pub fn insertNewline(self: *Self) Error!void {
pub fn insertNewline(self: *Self) WriteError!void {
_ = try self.writeNoIndent("\n");
}
@ -2634,7 +2634,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
}
/// Insert a newline unless the current line is blank
pub fn maybeInsertNewline(self: *Self) Error!void {
pub fn maybeInsertNewline(self: *Self) WriteError!void {
if (!self.current_line_empty)
try self.insertNewline();
}
@ -2675,7 +2675,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
}
/// Writes ' ' bytes if the current line is empty
fn applyIndent(self: *Self) Error!void {
fn applyIndent(self: *Self) WriteError!void {
const current_indent = self.currentIndent();
if (self.current_line_empty and current_indent > 0) {
if (self.disabled_offset == null) {

View File

@ -2353,6 +2353,7 @@ fn varDecl(
.name = ident_name,
.ptr = init_scope.rl_ptr,
.token_src = name_token,
.is_comptime = true,
};
return &sub_scope.base;
},
@ -2408,6 +2409,7 @@ fn varDecl(
.name = ident_name,
.ptr = var_data.alloc,
.token_src = name_token,
.is_comptime = is_comptime,
};
return &sub_scope.base;
},
@ -3352,7 +3354,7 @@ fn structDeclInner(
};
defer block_scope.instructions.deinit(gpa);
var namespace: Scope.Namespace = .{ .parent = &gz.base };
var namespace: Scope.Namespace = .{ .parent = scope };
defer namespace.decls.deinit(gpa);
var wip_decls: WipDecls = .{};
@ -5345,6 +5347,7 @@ fn forExpr(
.name = index_name,
.ptr = index_ptr,
.token_src = index_token,
.is_comptime = parent_gz.force_comptime,
};
break :blk &index_scope.base;
};
@ -6070,9 +6073,16 @@ fn identifier(
const name_str_index = try astgen.identAsString(ident_token);
{
var s = scope;
var found_already: ?ast.Node.Index = null; // we have found a decl with the same name already
var hit_namespace = false;
while (true) switch (s.tag) {
.local_val => {
const local_val = s.cast(Scope.LocalVal).?;
if (hit_namespace) {
// captures of non-locals need to be emitted as decl_val or decl_ref
// This *might* be capturable depending on if it is comptime known
break;
}
if (local_val.name == name_str_index) {
return rvalue(gz, scope, rl, local_val.inst, ident);
}
@ -6081,6 +6091,15 @@ fn identifier(
.local_ptr => {
const local_ptr = s.cast(Scope.LocalPtr).?;
if (local_ptr.name == name_str_index) {
if (hit_namespace) {
if (local_ptr.is_comptime)
break
else
return astgen.failNodeNotes(ident, "'{s}' not accessible from inner function", .{ident_name}, &.{
try astgen.errNoteTok(local_ptr.token_src, "declared here", .{}),
// TODO add crossed function definition here note.
});
}
switch (rl) {
.ref, .none_or_ref => return local_ptr.ptr,
else => {
@ -6093,7 +6112,22 @@ fn identifier(
},
.gen_zir => s = s.cast(GenZir).?.parent,
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
.namespace, .top => break, // TODO look for ambiguous references to decls
// look for ambiguous references to decls
.namespace => {
const ns = s.cast(Scope.Namespace).?;
if (ns.decls.get(name_str_index)) |i| {
if (found_already) |f|
return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{
try astgen.errNoteNode(i, "declared here", .{}),
try astgen.errNoteNode(f, "also declared here", .{}),
})
else
found_already = i;
}
hit_namespace = true;
s = ns.parent;
},
.top => break,
};
}
@ -8042,6 +8076,7 @@ const Scope = struct {
token_src: ast.TokenIndex,
/// String table index.
name: u32,
is_comptime: bool,
};
const Defer = struct {

View File

@ -943,6 +943,34 @@ pub fn addCases(ctx: *TestContext) !void {
":10:8: error: cannot return from defer expression",
});
ctx.compileError("ambiguous references", linux_x64,
\\const T = struct {
\\ const T = struct {
\\ fn f() void {
\\ _ = T;
\\ }
\\ };
\\};
, &.{
":4:17: error: ambiguous reference",
":1:1: note: declared here",
":2:5: note: also declared here",
});
ctx.compileError("inner func accessing outer var", linux_x64,
\\pub fn f() void {
\\ var bar: bool = true;
\\ const S = struct {
\\ fn baz() bool {
\\ return bar;
\\ }
\\ };
\\}
, &.{
":5:20: error: 'bar' not accessible from inner function",
":2:9: note: declared here",
});
ctx.compileError("global variable redeclaration", linux_x64,
\\// dummy comment
\\var foo = false;