Merge some cases of resolveTypeOfNodeInternal

This commit is contained in:
Jonathan Hähne 2021-04-05 15:26:06 +02:00
parent ea1ad532a2
commit 45c7f9671c

View File

@ -474,25 +474,22 @@ pub fn resolveReturnType(
if (fn_decl.ast.return_type == 0) return null; if (fn_decl.ast.return_type == 0) return null;
const return_type = fn_decl.ast.return_type; 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
return null;
const is_inferred_error = tree.tokens.items(.tag)[tree.firstToken(return_type) - 1] == .bang; const is_inferred_error = tree.tokens.items(.tag)[tree.firstToken(return_type) - 1] == .bang;
return if (is_inferred_error) block: { if (is_inferred_error) {
const child_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = return_type,
.handle = handle,
}, bound_type_params)) orelse return null;
const child_type_node = switch (child_type.type.data) { const child_type_node = switch (child_type.type.data) {
.other => |n| n, .other => |n| n,
else => return null, else => return null,
}; };
break :block TypeWithHandle{ return TypeWithHandle{
.type = .{ .data = .{ .error_union = child_type_node }, .is_type_val = false }, .type = .{ .data = .{ .error_union = child_type_node }, .is_type_val = false },
.handle = child_type.handle, .handle = child_type.handle,
}; };
} else ((try resolveTypeOfNodeInternal(store, arena, .{ } else
.node = return_type, return child_type.instanceTypeVal();
.handle = handle,
}, bound_type_params)) orelse return null).instanceTypeVal();
} }
/// Resolves the child type of an optional type /// Resolves the child type of an optional type
@ -591,7 +588,7 @@ fn resolveDerefType(
return null; return null;
} }
/// Resolves bracket access type (both slicing and array access) /// Resolves slicing and array access
fn resolveBracketAccessType( fn resolveBracketAccessType(
store: *DocumentStore, store: *DocumentStore,
arena: *std.heap.ArenaAllocator, arena: *std.heap.ArenaAllocator,
@ -684,17 +681,13 @@ pub fn resolveTypeOfNodeInternal(
node_handle: NodeWithHandle, node_handle: NodeWithHandle,
bound_type_params: *BoundTypeParams, bound_type_params: *BoundTypeParams,
) error{OutOfMemory}!?TypeWithHandle { ) error{OutOfMemory}!?TypeWithHandle {
const node = node_handle.node;
const handle = node_handle.handle;
const tree = handle.tree;
const state = struct { const state = struct {
var resolve_trail = std.ArrayListUnmanaged(NodeWithHandle){}; var resolve_trail = std.ArrayListUnmanaged(NodeWithHandle){};
}; };
// If we were asked to resolve this node before, // If we were asked to resolve this node before,
// it is self-referential and we cannot resolve it. // it is self-referential and we cannot resolve it.
for (state.resolve_trail.items) |i| { for (state.resolve_trail.items) |i| {
if (i.node == node and i.handle == handle) if (std.meta.eql(i, node_handle))
return null; return null;
} }
// We use the backing allocator here because the ArrayList expects its // We use the backing allocator here because the ArrayList expects its
@ -702,6 +695,10 @@ pub fn resolveTypeOfNodeInternal(
try state.resolve_trail.append(arena.child_allocator, node_handle); try state.resolve_trail.append(arena.child_allocator, node_handle);
defer _ = state.resolve_trail.pop(); defer _ = state.resolve_trail.pop();
const node = node_handle.node;
const handle = node_handle.handle;
const tree = handle.tree;
const main_tokens = tree.nodes.items(.main_token); const main_tokens = tree.nodes.items(.main_token);
const node_tags = tree.nodes.items(.tag); const node_tags = tree.nodes.items(.tag);
const datas = tree.nodes.items(.data); const datas = tree.nodes.items(.data);
@ -755,24 +752,6 @@ pub fn resolveTypeOfNodeInternal(
} }
return null; return null;
}, },
.container_field,
.container_field_init,
.container_field_align,
=> |c| {
const field: ast.full.ContainerField = switch (c) {
.container_field => tree.containerField(node),
.container_field_align => tree.containerFieldAlign(node),
.container_field_init => tree.containerFieldInit(node),
else => unreachable,
};
if (field.ast.type_expr == 0) return null;
const field_type = .{ .node = field.ast.type_expr, .handle = handle };
const typ = (try resolveTypeOfNodeInternal(store, arena, field_type, bound_type_params)) orelse
return null;
return typ.instanceTypeVal();
},
.call, .call,
.call_comma, .call_comma,
.async_call, .async_call,
@ -839,54 +818,63 @@ pub fn resolveTypeOfNodeInternal(
.@"comptime", .@"comptime",
.@"nosuspend", .@"nosuspend",
.grouped_expression, .grouped_expression,
=> { .container_field,
return try resolveTypeOfNodeInternal(store, arena, .{ .node = datas[node].lhs, .handle = handle }, bound_type_params); .container_field_init,
}, .container_field_align,
.struct_init, .struct_init,
.struct_init_comma, .struct_init_comma,
.struct_init_one, .struct_init_one,
.struct_init_one_comma, .struct_init_one_comma,
=> {
return ((try resolveTypeOfNodeInternal(
store,
arena,
.{ .node = datas[node].lhs, .handle = handle },
bound_type_params,
)) orelse return null).instanceTypeVal();
},
.error_set_decl => {
return TypeWithHandle.typeVal(node_handle);
},
.slice, .slice,
.slice_sentinel, .slice_sentinel,
.slice_open, .slice_open,
=> {
const left_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = datas[node].lhs,
.handle = handle,
}, bound_type_params)) orelse return null;
return try resolveBracketAccessType(store, arena, left_type, .Range, bound_type_params);
},
.deref, .deref,
.unwrap_optional, .unwrap_optional,
.array_access,
.@"orelse",
.@"catch",
.@"try",
.address_of,
=> { => {
const left_type = (try resolveTypeOfNodeInternal(store, arena, .{ const base = .{ .node = datas[node].lhs, .handle = handle };
.node = datas[node].lhs, const base_type = (try resolveTypeOfNodeInternal(store, arena, base, bound_type_params)) orelse
.handle = handle, return null;
}, bound_type_params)) orelse return null;
return switch (node_tags[node]) { return switch (node_tags[node]) {
.unwrap_optional => try resolveUnwrapOptionalType(store, arena, left_type, bound_type_params), .@"comptime",
.deref => try resolveDerefType(store, arena, left_type, bound_type_params), .@"nosuspend",
.grouped_expression,
=> base_type,
.container_field,
.container_field_init,
.container_field_align,
.struct_init,
.struct_init_comma,
.struct_init_one,
.struct_init_one_comma,
=> base_type.instanceTypeVal(),
.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),
.address_of => {
const lhs_node = switch (base_type.type.data) {
.other => |n| n,
else => return null,
};
return TypeWithHandle{
.type = .{ .data = .{ .pointer = lhs_node }, .is_type_val = base_type.type.is_type_val },
.handle = base_type.handle,
};
},
else => unreachable, else => unreachable,
}; };
}, },
.array_access => {
const left_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = datas[node].lhs,
.handle = handle,
}, bound_type_params)) orelse return null;
return try resolveBracketAccessType(store, arena, left_type, .Single, bound_type_params);
},
.field_access => { .field_access => {
const field_access = datas[node]; const field_access = datas[node];
@ -897,7 +885,7 @@ pub fn resolveTypeOfNodeInternal(
store, store,
arena, arena,
(try resolveTypeOfNodeInternal(store, arena, .{ (try resolveTypeOfNodeInternal(store, arena, .{
.node = field_access.lhs, .node = datas[node].lhs,
.handle = handle, .handle = handle,
}, bound_type_params)) orelse return null, }, bound_type_params)) orelse return null,
bound_type_params, bound_type_params,
@ -917,20 +905,6 @@ pub fn resolveTypeOfNodeInternal(
return try child.resolveType(store, arena, bound_type_params); return try child.resolveType(store, arena, bound_type_params);
} else return null; } else return null;
}, },
.@"orelse" => {
const left_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = datas[node].lhs,
.handle = handle,
}, bound_type_params)) orelse return null;
return try resolveUnwrapOptionalType(store, arena, left_type, bound_type_params);
},
.@"catch" => {
const left_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = datas[node].lhs,
.handle = handle,
}, bound_type_params)) orelse return null;
return try resolveUnwrapErrorType(store, arena, left_type, bound_type_params);
},
.array_type, .array_type,
.array_type_sentinel, .array_type_sentinel,
.optional_type, .optional_type,
@ -938,30 +912,20 @@ pub fn resolveTypeOfNodeInternal(
.ptr_type, .ptr_type,
.ptr_type_bit_range, .ptr_type_bit_range,
.error_union, .error_union,
.error_set_decl,
.container_decl,
.container_decl_arg,
.container_decl_arg_trailing,
.container_decl_trailing,
.container_decl_two,
.container_decl_two_trailing,
.tagged_union,
.tagged_union_trailing,
.tagged_union_two,
.tagged_union_two_trailing,
.tagged_union_enum_tag,
.tagged_union_enum_tag_trailing,
=> return TypeWithHandle.typeVal(node_handle), => return TypeWithHandle.typeVal(node_handle),
.@"try" => {
const rhs_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = datas[node].lhs,
.handle = handle,
}, bound_type_params)) orelse return null;
return try resolveUnwrapErrorType(store, arena, rhs_type, bound_type_params);
},
.address_of => {
const rhs_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = datas[node].lhs,
.handle = handle,
}, bound_type_params)) orelse return null;
const rhs_node = switch (rhs_type.type.data) {
.other => |n| n,
else => return null,
};
return TypeWithHandle{
.type = .{ .data = .{ .pointer = rhs_node }, .is_type_val = rhs_type.type.is_type_val },
.handle = rhs_type.handle,
};
},
.builtin_call, .builtin_call,
.builtin_call_comma, .builtin_call_comma,
.builtin_call_two, .builtin_call_two,
@ -1035,21 +999,6 @@ pub fn resolveTypeOfNodeInternal(
// reference to node '0' which is root // reference to node '0' which is root
return TypeWithHandle.typeVal(.{ .node = 0, .handle = new_handle }); return TypeWithHandle.typeVal(.{ .node = 0, .handle = new_handle });
}, },
.container_decl,
.container_decl_arg,
.container_decl_arg_trailing,
.container_decl_trailing,
.container_decl_two,
.container_decl_two_trailing,
.tagged_union,
.tagged_union_trailing,
.tagged_union_two,
.tagged_union_two_trailing,
.tagged_union_enum_tag,
.tagged_union_enum_tag_trailing,
=> {
return TypeWithHandle.typeVal(node_handle);
},
.fn_proto, .fn_proto,
.fn_proto_multi, .fn_proto_multi,
.fn_proto_one, .fn_proto_one,
@ -2726,14 +2675,15 @@ fn makeScopeInternal(
} }
// Visit parameter types to pick up any error sets and enum // Visit parameter types to pick up any error sets and enum
// completions // completions
if (param.type_expr != 0) try makeScopeInternal( if (param.type_expr != 0)
allocator, try makeScopeInternal(
scopes, allocator,
error_completions, scopes,
enum_completions, error_completions,
tree, enum_completions,
param.type_expr, tree,
); param.type_expr,
);
} }
if (fn_tag == .fn_decl) blk: { if (fn_tag == .fn_decl) blk: {
@ -2964,17 +2914,20 @@ fn makeScopeInternal(
std.debug.assert(token_tags[name_token] == .identifier); std.debug.assert(token_tags[name_token] == .identifier);
const name = tree.tokenSlice(name_token); const name = tree.tokenSlice(name_token);
try scope.decls.putNoClobber(name, if (is_for) .{ try scope.decls.putNoClobber(name, if (is_for)
.array_payload = .{ .{
.identifier = name_token, .array_payload = .{
.array_expr = while_node.ast.cond_expr, .identifier = name_token,
}, .array_expr = while_node.ast.cond_expr,
} else .{ },
.pointer_payload = .{ }
.name = name_token, else
.condition = while_node.ast.cond_expr, .{
}, .pointer_payload = .{
}); .name = name_token,
.condition = while_node.ast.cond_expr,
},
});
// for loop with index as well // for loop with index as well
if (token_tags[name_token + 1] == .comma) { if (token_tags[name_token + 1] == .comma) {