remove arena allocator from analysis (#981)

* remove arena allocator from analysis

* fuzzer fix

* deinit `BoundTypeParams`
This commit is contained in:
Techatrix
2023-02-07 22:44:04 +00:00
committed by GitHub
parent 1b3274aa9c
commit 8ec82321d4
7 changed files with 156 additions and 164 deletions

View File

@@ -185,7 +185,7 @@ pub fn getFunctionSnippet(allocator: std.mem.Allocator, tree: Ast, func: Ast.ful
return buffer.toOwnedSlice(allocator);
}
pub fn hasSelfParam(arena: *std.heap.ArenaAllocator, document_store: *DocumentStore, handle: *const DocumentStore.Handle, func: Ast.full.FnProto) !bool {
pub fn hasSelfParam(document_store: *DocumentStore, handle: *const DocumentStore.Handle, func: Ast.full.FnProto) !bool {
// Non-decl prototypes cannot have a self parameter.
if (func.name_token == null) return false;
if (func.ast.params.len == 0) return false;
@@ -198,7 +198,7 @@ pub fn hasSelfParam(arena: *std.heap.ArenaAllocator, document_store: *DocumentSt
const token_starts = tree.tokens.items(.start);
const in_container = innermostContainer(handle, token_starts[func.ast.fn_token]);
if (try resolveTypeOfNode(document_store, arena, .{
if (try resolveTypeOfNode(document_store, .{
.node = param.type_expr,
.handle = handle,
})) |resolved_type| {
@@ -207,7 +207,7 @@ pub fn hasSelfParam(arena: *std.heap.ArenaAllocator, document_store: *DocumentSt
}
if (ast.fullPtrType(tree, param.type_expr)) |ptr_type| {
if (try resolveTypeOfNode(document_store, arena, .{
if (try resolveTypeOfNode(document_store, .{
.node = ptr_type.ast.child_type,
.handle = handle,
})) |resolved_prefix_op| {
@@ -322,7 +322,7 @@ pub fn getDeclName(tree: Ast, node: Ast.Node.Index) ?[]const u8 {
};
}
fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, node_handle: NodeWithHandle, root: bool) error{OutOfMemory}!?DeclWithHandle {
fn resolveVarDeclAliasInternal(store: *DocumentStore, node_handle: NodeWithHandle, root: bool) error{OutOfMemory}!?DeclWithHandle {
_ = root;
const handle = node_handle.handle;
const tree = handle.tree;
@@ -334,7 +334,6 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
const token = main_tokens[node_handle.node];
return try lookupSymbolGlobal(
store,
arena,
handle,
tree.tokenSlice(token),
tree.tokens.items(.start)[token],
@@ -349,13 +348,13 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
if (!std.mem.eql(u8, name, "@import") and !std.mem.eql(u8, name, "@cImport"))
return null;
const inner_node = (try resolveTypeOfNode(store, arena, .{ .node = lhs, .handle = handle })) orelse return null;
const inner_node = (try resolveTypeOfNode(store, .{ .node = lhs, .handle = handle })) orelse return null;
// assert root node
std.debug.assert(inner_node.type.data.other == 0);
break :block NodeWithHandle{ .node = inner_node.type.data.other, .handle = inner_node.handle };
} else if (try resolveVarDeclAliasInternal(store, arena, .{ .node = lhs, .handle = handle }, false)) |decl_handle| block: {
} else if (try resolveVarDeclAliasInternal(store, .{ .node = lhs, .handle = handle }, false)) |decl_handle| block: {
if (decl_handle.decl.* != .ast_node) return null;
const resolved = (try resolveTypeOfNode(store, arena, .{ .node = decl_handle.decl.ast_node, .handle = decl_handle.handle })) orelse return null;
const resolved = (try resolveTypeOfNode(store, .{ .node = decl_handle.decl.ast_node, .handle = decl_handle.handle })) orelse return null;
const resolved_node = switch (resolved.type.data) {
.other => |n| n,
else => return null,
@@ -364,7 +363,7 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
break :block NodeWithHandle{ .node = resolved_node, .handle = resolved.handle };
} else return null;
return try lookupSymbolContainer(store, arena, container_node, tree.tokenSlice(datas[node_handle.node].rhs), false);
return try lookupSymbolContainer(store, container_node, tree.tokenSlice(datas[node_handle.node].rhs), false);
}
return null;
}
@@ -375,7 +374,7 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
/// const decl = @import("decl-file.zig").decl;
/// const other = decl.middle.other;
///```
pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocator, decl_handle: NodeWithHandle) !?DeclWithHandle {
pub fn resolveVarDeclAlias(store: *DocumentStore, decl_handle: NodeWithHandle) !?DeclWithHandle {
const decl = decl_handle.node;
const handle = decl_handle.handle;
const tree = handle.tree;
@@ -392,7 +391,7 @@ pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocato
if (!std.mem.eql(u8, tree.tokenSlice(var_decl.ast.mut_token + 1), name))
return null;
return try resolveVarDeclAliasInternal(store, arena, .{ .node = base_exp, .handle = handle }, true);
return try resolveVarDeclAliasInternal(store, .{ .node = base_exp, .handle = handle }, true);
}
}
@@ -440,7 +439,7 @@ fn findReturnStatement(tree: Ast, fn_decl: Ast.full.FnProto, body: Ast.Node.Inde
return findReturnStatementInternal(tree, fn_decl, body, &already_found);
}
pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, fn_decl: Ast.full.FnProto, handle: *const DocumentStore.Handle, bound_type_params: *BoundTypeParams, fn_body: ?Ast.Node.Index) !?TypeWithHandle {
pub fn resolveReturnType(store: *DocumentStore, fn_decl: Ast.full.FnProto, handle: *const DocumentStore.Handle, bound_type_params: *BoundTypeParams, fn_body: ?Ast.Node.Index) !?TypeWithHandle {
const tree = handle.tree;
if (isTypeFunction(tree, fn_decl) and fn_body != null) {
// If this is a type function and it only contains a single return statement that returns
@@ -448,7 +447,7 @@ pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
const ret = findReturnStatement(tree, fn_decl, fn_body.?) orelse return null;
const data = tree.nodes.items(.data)[ret];
if (data.lhs != 0) {
return try resolveTypeOfNodeInternal(store, arena, .{
return try resolveTypeOfNodeInternal(store, .{
.node = data.lhs,
.handle = handle,
}, bound_type_params);
@@ -460,7 +459,7 @@ pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
if (fn_decl.ast.return_type == 0) return null;
const return_type = fn_decl.ast.return_type;
const ret = .{ .node = return_type, .handle = handle };
const child_type = (try resolveTypeOfNodeInternal(store, arena, ret, bound_type_params)) orelse
const child_type = (try resolveTypeOfNodeInternal(store, ret, bound_type_params)) orelse
return null;
const is_inferred_error = tree.tokens.items(.tag)[tree.firstToken(return_type) - 1] == .bang;
@@ -477,14 +476,14 @@ pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
}
/// Resolves the child type of an optional type
fn resolveUnwrapOptionalType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, opt: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
fn resolveUnwrapOptionalType(store: *DocumentStore, opt: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
const opt_node = switch (opt.type.data) {
.other => |n| n,
else => return null,
};
if (opt.handle.tree.nodes.items(.tag)[opt_node] == .optional_type) {
return ((try resolveTypeOfNodeInternal(store, arena, .{
return ((try resolveTypeOfNodeInternal(store, .{
.node = opt.handle.tree.nodes.items(.data)[opt_node].lhs,
.handle = opt.handle,
}, bound_type_params)) orelse return null).instanceTypeVal();
@@ -493,7 +492,7 @@ fn resolveUnwrapOptionalType(store: *DocumentStore, arena: *std.heap.ArenaAlloca
return null;
}
fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, rhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
fn resolveUnwrapErrorType(store: *DocumentStore, rhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
const rhs_node = switch (rhs.type.data) {
.other => |n| n,
.error_union => |n| return TypeWithHandle{
@@ -504,7 +503,7 @@ fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
};
if (rhs.handle.tree.nodes.items(.tag)[rhs_node] == .error_union) {
return ((try resolveTypeOfNodeInternal(store, arena, .{
return ((try resolveTypeOfNodeInternal(store, .{
.node = rhs.handle.tree.nodes.items(.data)[rhs_node].rhs,
.handle = rhs.handle,
}, bound_type_params)) orelse return null).instanceTypeVal();
@@ -514,7 +513,7 @@ fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
}
/// Resolves the child type of a deref type
fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, deref: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
fn resolveDerefType(store: *DocumentStore, deref: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
const deref_node = switch (deref.type.data) {
.other => |n| n,
.pointer => |n| return TypeWithHandle{
@@ -533,7 +532,7 @@ fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, dere
if (ast.fullPtrType(tree, deref_node)) |ptr_type| {
switch (token_tag) {
.asterisk => {
return ((try resolveTypeOfNodeInternal(store, arena, .{
return ((try resolveTypeOfNodeInternal(store, .{
.node = ptr_type.ast.child_type,
.handle = deref.handle,
}, bound_type_params)) orelse return null).instanceTypeVal();
@@ -546,7 +545,7 @@ fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, dere
}
/// Resolves slicing and array access
fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, lhs: TypeWithHandle, rhs: enum { Single, Range }, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
fn resolveBracketAccessType(store: *DocumentStore, lhs: TypeWithHandle, rhs: enum { Single, Range }, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
const lhs_node = switch (lhs.type.data) {
.other => |n| n,
else => return null,
@@ -559,7 +558,7 @@ fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocat
if (tag == .array_type or tag == .array_type_sentinel) {
if (rhs == .Single)
return ((try resolveTypeOfNodeInternal(store, arena, .{
return ((try resolveTypeOfNodeInternal(store, .{
.node = data.rhs,
.handle = lhs.handle,
}, bound_type_params)) orelse return null).instanceTypeVal();
@@ -570,7 +569,7 @@ fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocat
} else if (ast.fullPtrType(tree, lhs_node)) |ptr_type| {
if (ptr_type.size == .Slice) {
if (rhs == .Single) {
return ((try resolveTypeOfNodeInternal(store, arena, .{
return ((try resolveTypeOfNodeInternal(store, .{
.node = ptr_type.ast.child_type,
.handle = lhs.handle,
}, bound_type_params)) orelse return null).instanceTypeVal();
@@ -583,8 +582,8 @@ fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocat
}
/// Called to remove one level of pointerness before a field access
pub fn resolveFieldAccessLhsType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, lhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !TypeWithHandle {
return (try resolveDerefType(store, arena, lhs, bound_type_params)) orelse lhs;
pub fn resolveFieldAccessLhsType(store: *DocumentStore, lhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !TypeWithHandle {
return (try resolveDerefType(store, lhs, bound_type_params)) orelse lhs;
}
pub const BoundTypeParams = std.AutoHashMapUnmanaged(Ast.full.FnProto.Param, TypeWithHandle);
@@ -622,7 +621,7 @@ pub fn isTypeIdent(text: []const u8) bool {
}
/// Resolves the type of a node
pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, node_handle: NodeWithHandle, bound_type_params: *BoundTypeParams) error{OutOfMemory}!?TypeWithHandle {
pub fn resolveTypeOfNodeInternal(store: *DocumentStore, node_handle: NodeWithHandle, bound_type_params: *BoundTypeParams) error{OutOfMemory}!?TypeWithHandle {
// If we were asked to resolve this node before,
// it is self-referential and we cannot resolve it.
for (resolve_trail.items) |i| {
@@ -651,14 +650,14 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
const var_decl = tree.fullVarDecl(node).?;
if (var_decl.ast.type_node != 0) {
const decl_type = .{ .node = var_decl.ast.type_node, .handle = handle };
if (try resolveTypeOfNodeInternal(store, arena, decl_type, bound_type_params)) |typ|
if (try resolveTypeOfNodeInternal(store, decl_type, bound_type_params)) |typ|
return typ.instanceTypeVal();
}
if (var_decl.ast.init_node == 0)
return null;
const value = .{ .node = var_decl.ast.init_node, .handle = handle };
return try resolveTypeOfNodeInternal(store, arena, value, bound_type_params);
return try resolveTypeOfNodeInternal(store, value, bound_type_params);
},
.identifier => {
const name = offsets.nodeToSlice(tree, node);
@@ -672,7 +671,6 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
if (try lookupSymbolGlobal(
store,
arena,
handle,
name,
starts[main_tokens[node]],
@@ -687,7 +685,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
},
else => {},
}
return try child.resolveType(store, arena, bound_type_params);
return try child.resolveType(store, bound_type_params);
}
return null;
},
@@ -704,7 +702,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
const call = tree.fullCall(&params, node) orelse unreachable;
const callee = .{ .node = call.ast.fn_expr, .handle = handle };
const decl = (try resolveTypeOfNodeInternal(store, arena, callee, bound_type_params)) orelse
const decl = (try resolveTypeOfNodeInternal(store, callee, bound_type_params)) orelse
return null;
if (decl.type.is_type_val) return null;
@@ -721,7 +719,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
// TODO: Back-parse to extract the self argument?
var it = fn_decl.iterate(&decl.handle.tree);
if (token_tags[call.ast.lparen - 2] == .period) {
if (try hasSelfParam(arena, store, decl.handle, fn_decl)) {
if (try hasSelfParam(store, decl.handle, fn_decl)) {
_ = ast.nextFnParam(&it);
expected_params -= 1;
}
@@ -738,19 +736,18 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
const argument = .{ .node = call.ast.params[i], .handle = handle };
const argument_type = (try resolveTypeOfNodeInternal(
store,
arena,
argument,
bound_type_params,
)) orelse
continue;
if (!argument_type.type.is_type_val) continue;
try bound_type_params.put(arena.allocator(), decl_param, argument_type);
try bound_type_params.put(store.allocator, decl_param, argument_type);
}
const has_body = decl.handle.tree.nodes.items(.tag)[decl_node] == .fn_decl;
const body = decl.handle.tree.nodes.items(.data)[decl_node].rhs;
if (try resolveReturnType(store, arena, fn_decl, decl.handle, bound_type_params, if (has_body) body else null)) |ret| {
if (try resolveReturnType(store, fn_decl, decl.handle, bound_type_params, if (has_body) body else null)) |ret| {
return ret;
} else if (store.config.use_comptime_interpreter) {
// TODO: Better case-by-case; we just use the ComptimeInterpreter when all else fails,
@@ -829,7 +826,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
.address_of,
=> {
const base = .{ .node = datas[node].lhs, .handle = handle };
const base_type = (try resolveTypeOfNodeInternal(store, arena, base, bound_type_params)) orelse
const base_type = (try resolveTypeOfNodeInternal(store, base, bound_type_params)) orelse
return null;
return switch (node_tags[node]) {
.@"comptime",
@@ -847,13 +844,13 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
.slice,
.slice_sentinel,
.slice_open,
=> try resolveBracketAccessType(store, arena, base_type, .Range, bound_type_params),
.deref => try resolveDerefType(store, arena, base_type, bound_type_params),
.unwrap_optional => try resolveUnwrapOptionalType(store, arena, base_type, bound_type_params),
.array_access => try resolveBracketAccessType(store, arena, base_type, .Single, bound_type_params),
.@"orelse" => try resolveUnwrapOptionalType(store, arena, base_type, bound_type_params),
.@"catch" => try resolveUnwrapErrorType(store, arena, base_type, bound_type_params),
.@"try" => try resolveUnwrapErrorType(store, arena, base_type, bound_type_params),
=> try resolveBracketAccessType(store, base_type, .Range, bound_type_params),
.deref => try resolveDerefType(store, base_type, bound_type_params),
.unwrap_optional => try resolveUnwrapOptionalType(store, base_type, bound_type_params),
.array_access => try resolveBracketAccessType(store, base_type, .Single, bound_type_params),
.@"orelse" => try resolveUnwrapOptionalType(store, base_type, bound_type_params),
.@"catch" => try resolveUnwrapErrorType(store, base_type, bound_type_params),
.@"try" => try resolveUnwrapErrorType(store, base_type, bound_type_params),
.address_of => {
const lhs_node = switch (base_type.type.data) {
.other => |n| n,
@@ -873,8 +870,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
// If we are accessing a pointer type, remove one pointerness level :)
const left_type = try resolveFieldAccessLhsType(
store,
arena,
(try resolveTypeOfNodeInternal(store, arena, .{
(try resolveTypeOfNodeInternal(store, .{
.node = datas[node].lhs,
.handle = handle,
}, bound_type_params)) orelse return null,
@@ -888,12 +884,11 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
if (try lookupSymbolContainer(
store,
arena,
.{ .node = left_type_node, .handle = left_type.handle },
tree.tokenSlice(datas[node].rhs),
!left_type.type.is_type_val,
)) |child| {
return try child.resolveType(store, arena, bound_type_params);
return try child.resolveType(store, bound_type_params);
} else return null;
},
.array_type,
@@ -947,7 +942,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
});
if (cast_map.has(call_name)) {
if (params.len < 1) return null;
return ((try resolveTypeOfNodeInternal(store, arena, .{
return ((try resolveTypeOfNodeInternal(store, .{
.node = params[0],
.handle = handle,
}, bound_type_params)) orelse return null).instanceTypeVal();
@@ -957,7 +952,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
// TODO Do peer type resolution, we just keep the first for now.
if (std.mem.eql(u8, call_name, "@TypeOf")) {
if (params.len < 1) return null;
var resolved_type = (try resolveTypeOfNodeInternal(store, arena, .{
var resolved_type = (try resolveTypeOfNodeInternal(store, .{
.node = params[0],
.handle = handle,
}, bound_type_params)) orelse return null;
@@ -968,12 +963,14 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
}
if (std.mem.eql(u8, call_name, "@typeInfo")) {
const zig_lib_path = try URI.fromPath(arena.allocator(), store.config.zig_lib_path orelse return null);
const zig_lib_path = try URI.fromPath(store.allocator, store.config.zig_lib_path orelse return null);
defer store.allocator.free(zig_lib_path);
const builtin_uri = URI.pathRelative(arena.allocator(), zig_lib_path, "/std/builtin.zig") catch |err| switch (err) {
const builtin_uri = URI.pathRelative(store.allocator, zig_lib_path, "/std/builtin.zig") catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => return null,
};
defer store.allocator.free(builtin_uri);
const new_handle = store.getOrLoadHandle(builtin_uri) orelse return null;
const root_scope_decls = new_handle.document_scope.scopes.items(.decls)[0];
@@ -997,7 +994,8 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
if (node_tags[import_param] != .string_literal) return null;
const import_str = tree.tokenSlice(main_tokens[import_param]);
const import_uri = (try store.uriFromImportStr(arena.allocator(), handle.*, import_str[1 .. import_str.len - 1])) orelse return null;
const import_uri = (try store.uriFromImportStr(store.allocator, handle.*, import_str[1 .. import_str.len - 1])) orelse return null;
defer store.allocator.free(import_uri);
const new_handle = store.getOrLoadHandle(import_uri) orelse return null;
@@ -1168,9 +1166,10 @@ pub const TypeWithHandle = struct {
}
};
pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator, node_handle: NodeWithHandle) error{OutOfMemory}!?TypeWithHandle {
pub fn resolveTypeOfNode(store: *DocumentStore, node_handle: NodeWithHandle) error{OutOfMemory}!?TypeWithHandle {
var bound_type_params = BoundTypeParams{};
return resolveTypeOfNodeInternal(store, arena, node_handle, &bound_type_params);
defer bound_type_params.deinit(store.allocator);
return resolveTypeOfNodeInternal(store, node_handle, &bound_type_params);
}
/// Collects all `@import`'s we can find into a slice of import paths (without quotes).
@@ -1236,28 +1235,28 @@ pub const FieldAccessReturn = struct {
unwrapped: ?TypeWithHandle = null,
};
pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, source_index: usize, tokenizer: *std.zig.Tokenizer) !?FieldAccessReturn {
pub fn getFieldAccessType(store: *DocumentStore, handle: *const DocumentStore.Handle, source_index: usize, tokenizer: *std.zig.Tokenizer) !?FieldAccessReturn {
var current_type: ?TypeWithHandle = null;
var bound_type_params = BoundTypeParams{};
defer bound_type_params.deinit(store.allocator);
while (true) {
const tok = tokenizer.next();
switch (tok.tag) {
.eof => return FieldAccessReturn{
.original = current_type orelse return null,
.unwrapped = try resolveDerefType(store, arena, current_type orelse return null, &bound_type_params),
.unwrapped = try resolveDerefType(store, current_type orelse return null, &bound_type_params),
},
.identifier => {
const ct_handle = if (current_type) |c| c.handle else handle;
if (try lookupSymbolGlobal(
store,
arena,
ct_handle,
tokenizer.buffer[tok.loc.start..tok.loc.end],
source_index,
)) |child| {
current_type = (try child.resolveType(store, arena, &bound_type_params)) orelse return null;
current_type = (try child.resolveType(store, &bound_type_params)) orelse return null;
} else return null;
},
.period => {
@@ -1269,7 +1268,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
if (ct.isFunc()) return null;
return FieldAccessReturn{
.original = ct,
.unwrapped = try resolveDerefType(store, arena, ct, &bound_type_params),
.unwrapped = try resolveDerefType(store, ct, &bound_type_params),
};
} else {
return null;
@@ -1280,14 +1279,14 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
if (current_type) |ct| {
return FieldAccessReturn{
.original = ct,
.unwrapped = try resolveDerefType(store, arena, ct, &bound_type_params),
.unwrapped = try resolveDerefType(store, ct, &bound_type_params),
};
} else {
return null;
}
}
current_type = try resolveFieldAccessLhsType(store, arena, current_type orelse return null, &bound_type_params);
current_type = try resolveFieldAccessLhsType(store, current_type orelse return null, &bound_type_params);
const current_type_node = switch (current_type.?.type.data) {
.other => |n| n,
@@ -1296,14 +1295,12 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
if (try lookupSymbolContainer(
store,
arena,
.{ .node = current_type_node, .handle = current_type.?.handle },
tokenizer.buffer[after_period.loc.start..after_period.loc.end],
!current_type.?.type.is_type_val,
)) |child| {
current_type.? = (try child.resolveType(
store,
arena,
&bound_type_params,
)) orelse return null;
} else return null;
@@ -1311,7 +1308,6 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
.question_mark => {
current_type = (try resolveUnwrapOptionalType(
store,
arena,
current_type orelse return null,
&bound_type_params,
)) orelse return null;
@@ -1325,7 +1321,6 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
.period_asterisk => {
current_type = (try resolveDerefType(
store,
arena,
current_type orelse return null,
&bound_type_params,
)) orelse return null;
@@ -1351,7 +1346,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
const body = cur_tree.nodes.items(.data)[current_type_node].rhs;
// TODO Actually bind params here when calling functions instead of just skipping args.
if (try resolveReturnType(store, arena, func, current_type.?.handle, &bound_type_params, if (has_body) body else null)) |ret| {
if (try resolveReturnType(store, func, current_type.?.handle, &bound_type_params, if (has_body) body else null)) |ret| {
current_type = ret;
// Skip to the right paren
var paren_count: usize = 1;
@@ -1382,7 +1377,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
}
} else return null;
current_type = (try resolveBracketAccessType(store, arena, current_type orelse return null, if (is_range) .Range else .Single, &bound_type_params)) orelse return null;
current_type = (try resolveBracketAccessType(store, current_type orelse return null, if (is_range) .Range else .Single, &bound_type_params)) orelse return null;
},
else => {
log.debug("Unimplemented token: {}", .{tok.tag});
@@ -1394,7 +1389,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
if (current_type) |ct| {
return FieldAccessReturn{
.original = ct,
.unwrapped = try resolveDerefType(store, arena, ct, &bound_type_params),
.unwrapped = try resolveDerefType(store, ct, &bound_type_params),
};
} else {
return null;
@@ -2022,14 +2017,13 @@ pub const DeclWithHandle = struct {
};
}
pub fn resolveType(self: DeclWithHandle, store: *DocumentStore, arena: *std.heap.ArenaAllocator, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
pub fn resolveType(self: DeclWithHandle, store: *DocumentStore, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
const tree = self.handle.tree;
const node_tags = tree.nodes.items(.tag);
const main_tokens = tree.nodes.items(.main_token);
return switch (self.decl.*) {
.ast_node => |node| try resolveTypeOfNodeInternal(
store,
arena,
.{ .node = node, .handle = self.handle },
bound_type_params,
),
@@ -2049,15 +2043,13 @@ pub const DeclWithHandle = struct {
}
return ((try resolveTypeOfNodeInternal(
store,
arena,
.{ .node = param_decl.type_expr, .handle = self.handle },
bound_type_params,
)) orelse return null).instanceTypeVal();
},
.pointer_payload => |pay| try resolveUnwrapOptionalType(
store,
arena,
(try resolveTypeOfNodeInternal(store, arena, .{
(try resolveTypeOfNodeInternal(store, .{
.node = pay.condition,
.handle = self.handle,
}, bound_type_params)) orelse return null,
@@ -2065,8 +2057,7 @@ pub const DeclWithHandle = struct {
),
.array_payload => |pay| try resolveBracketAccessType(
store,
arena,
(try resolveTypeOfNodeInternal(store, arena, .{
(try resolveTypeOfNodeInternal(store, .{
.node = pay.array_expr,
.handle = self.handle,
}, bound_type_params)) orelse return null,
@@ -2081,7 +2072,7 @@ pub const DeclWithHandle = struct {
.switch_payload => |pay| {
if (pay.items.len == 0) return null;
// TODO Peer type resolution, we just use the first item for now.
const switch_expr_type = (try resolveTypeOfNodeInternal(store, arena, .{
const switch_expr_type = (try resolveTypeOfNodeInternal(store, .{
.node = pay.switch_expr,
.handle = self.handle,
}, bound_type_params)) orelse return null;
@@ -2101,7 +2092,6 @@ pub const DeclWithHandle = struct {
if (container_field.ast.type_expr != 0) {
return ((try resolveTypeOfNodeInternal(
store,
arena,
.{ .node = container_field.ast.type_expr, .handle = switch_expr_type.handle },
bound_type_params,
)) orelse return null).instanceTypeVal();
@@ -2133,7 +2123,7 @@ fn findContainerScopeIndex(container_handle: NodeWithHandle) ?usize {
} else null;
}
fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
fn iterateSymbolsContainerInternal(store: *DocumentStore, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
const container = container_handle.node;
const handle = container_handle.handle;
@@ -2180,7 +2170,7 @@ fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.Arena
try use_trail.append(use);
const lhs = tree.nodes.items(.data)[use].lhs;
const use_expr = (try resolveTypeOfNode(store, arena, .{
const use_expr = (try resolveTypeOfNode(store, .{
.node = lhs,
.handle = handle,
})) orelse continue;
@@ -2191,7 +2181,6 @@ fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.Arena
};
try iterateSymbolsContainerInternal(
store,
arena,
.{ .node = use_expr_node, .handle = use_expr.handle },
orig_handle,
callback,
@@ -2232,9 +2221,10 @@ pub fn iterateEnclosingScopes(document_scope: DocumentScope, source_index: usize
};
}
pub fn iterateSymbolsContainer(store: *DocumentStore, arena: *std.heap.ArenaAllocator, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool) error{OutOfMemory}!void {
var use_trail = std.ArrayList(Ast.Node.Index).init(arena.allocator());
return try iterateSymbolsContainerInternal(store, arena, container_handle, orig_handle, callback, context, instance_access, &use_trail);
pub fn iterateSymbolsContainer(store: *DocumentStore, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool) error{OutOfMemory}!void {
var use_trail = std.ArrayList(Ast.Node.Index).init(store.allocator);
defer use_trail.deinit();
return try iterateSymbolsContainerInternal(store, container_handle, orig_handle, callback, context, instance_access, &use_trail);
}
pub fn iterateLabels(handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
@@ -2253,7 +2243,7 @@ pub fn iterateLabels(handle: *const DocumentStore.Handle, source_index: usize, c
}
}
fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
fn iterateSymbolsGlobalInternal(store: *DocumentStore, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
const scope_decls = handle.document_scope.scopes.items(.decls);
const scope_uses = handle.document_scope.scopes.items(.uses);
@@ -2273,7 +2263,6 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
const use_expr = (try resolveTypeOfNode(
store,
arena,
.{ .node = handle.tree.nodes.items(.data)[use].lhs, .handle = handle },
)) orelse continue;
const use_expr_node = switch (use_expr.type.data) {
@@ -2282,7 +2271,6 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
};
try iterateSymbolsContainerInternal(
store,
arena,
.{ .node = use_expr_node, .handle = use_expr.handle },
handle,
callback,
@@ -2294,9 +2282,10 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
}
}
pub fn iterateSymbolsGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
var use_trail = std.ArrayList(Ast.Node.Index).init(arena.allocator());
return try iterateSymbolsGlobalInternal(store, arena, handle, source_index, callback, context, &use_trail);
pub fn iterateSymbolsGlobal(store: *DocumentStore, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
var use_trail = std.ArrayList(Ast.Node.Index).init(store.allocator);
defer use_trail.deinit();
return try iterateSymbolsGlobalInternal(store, handle, source_index, callback, context, &use_trail);
}
pub fn innermostBlockScopeIndex(handle: DocumentStore.Handle, source_index: usize) usize {
@@ -2341,7 +2330,7 @@ pub fn innermostContainer(handle: *const DocumentStore.Handle, source_index: usi
return TypeWithHandle.typeVal(.{ .node = current, .handle = handle });
}
fn resolveUse(store: *DocumentStore, arena: *std.heap.ArenaAllocator, uses: []const Ast.Node.Index, symbol: []const u8, handle: *const DocumentStore.Handle) error{OutOfMemory}!?DeclWithHandle {
fn resolveUse(store: *DocumentStore, uses: []const Ast.Node.Index, symbol: []const u8, handle: *const DocumentStore.Handle) error{OutOfMemory}!?DeclWithHandle {
if (uses.len == 0) return null;
// If we were asked to resolve this symbol before,
@@ -2355,7 +2344,7 @@ fn resolveUse(store: *DocumentStore, arena: *std.heap.ArenaAllocator, uses: []co
if (handle.tree.nodes.items(.data).len <= index) continue;
const expr = .{ .node = handle.tree.nodes.items(.data)[index].lhs, .handle = handle };
const expr_type_node = (try resolveTypeOfNode(store, arena, expr)) orelse
const expr_type_node = (try resolveTypeOfNode(store, expr)) orelse
continue;
const expr_type = .{
@@ -2366,7 +2355,7 @@ fn resolveUse(store: *DocumentStore, arena: *std.heap.ArenaAllocator, uses: []co
.handle = expr_type_node.handle,
};
if (try lookupSymbolContainer(store, arena, expr_type, symbol, false)) |candidate| {
if (try lookupSymbolContainer(store, expr_type, symbol, false)) |candidate| {
if (candidate.handle == handle or candidate.isPublic()) {
return candidate;
}
@@ -2394,7 +2383,7 @@ pub fn lookupLabel(handle: *const DocumentStore.Handle, symbol: []const u8, sour
return null;
}
pub fn lookupSymbolGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, symbol: []const u8, source_index: usize) error{OutOfMemory}!?DeclWithHandle {
pub fn lookupSymbolGlobal(store: *DocumentStore, handle: *const DocumentStore.Handle, symbol: []const u8, source_index: usize) error{OutOfMemory}!?DeclWithHandle {
const innermost_scope_idx = innermostBlockScopeIndex(handle.*, source_index);
const scope_locs = handle.document_scope.scopes.items(.loc);
@@ -2418,7 +2407,7 @@ pub fn lookupSymbolGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator
.handle = handle,
};
}
if (try resolveUse(store, arena, scope_uses[curr].items, symbol, handle)) |result| return result;
if (try resolveUse(store, scope_uses[curr].items, symbol, handle)) |result| return result;
}
if (curr == 0) break;
}
@@ -2427,7 +2416,6 @@ pub fn lookupSymbolGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator
pub fn lookupSymbolContainer(
store: *DocumentStore,
arena: *std.heap.ArenaAllocator,
container_handle: NodeWithHandle,
symbol: []const u8,
/// If true, we are looking up the symbol like we are accessing through a field access
@@ -2460,7 +2448,7 @@ pub fn lookupSymbolContainer(
return DeclWithHandle{ .decl = candidate.value_ptr, .handle = handle };
}
if (try resolveUse(store, arena, scope_uses[container_scope_index].items, symbol, handle)) |result| return result;
if (try resolveUse(store, scope_uses[container_scope_index].items, symbol, handle)) |result| return result;
}
return null;