Type resolving fixes
This commit is contained in:
parent
96fcac89a4
commit
b651a79380
198
src/analysis.zig
198
src/analysis.zig
@ -132,7 +132,7 @@ pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: ast.Tree, func: *
|
|||||||
|
|
||||||
if (curr_token == end_token and is_comma) continue;
|
if (curr_token == end_token and is_comma) continue;
|
||||||
try buffer.appendSlice(tree.tokenSlice(curr_token));
|
try buffer.appendSlice(tree.tokenSlice(curr_token));
|
||||||
if (is_comma or tag == .Keyword_const) try buffer.append(' ');
|
if (is_comma or tag == .keyword_const) try buffer.append(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try buffer.append('}');
|
try buffer.append('}');
|
||||||
@ -240,7 +240,7 @@ fn getDeclName(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
|
|||||||
|
|
||||||
fn isContainerDecl(decl_handle: DeclWithHandle) bool {
|
fn isContainerDecl(decl_handle: DeclWithHandle) bool {
|
||||||
return switch (decl_handle.decl.*) {
|
return switch (decl_handle.decl.*) {
|
||||||
.ast_node => |inner_node| inner_node.tag == .ContainerDecl or inner_node.tag == .Root,
|
.ast_node => |inner_node| isContainer(decl_handle.handle.tree.nodes.items(.tag)[inner_node]) or inner_node == 0,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -370,21 +370,18 @@ fn resolveUnwrapOptionalType(
|
|||||||
arena: *std.heap.ArenaAllocator,
|
arena: *std.heap.ArenaAllocator,
|
||||||
opt: TypeWithHandle,
|
opt: TypeWithHandle,
|
||||||
bound_type_params: *BoundTypeParams,
|
bound_type_params: *BoundTypeParams,
|
||||||
tree: ast.Tree,
|
|
||||||
) !?TypeWithHandle {
|
) !?TypeWithHandle {
|
||||||
const opt_node = switch (opt.type.data) {
|
const opt_node = switch (opt.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
else => return null,
|
else => return null,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (opt_node.cast(ast.Node.SimplePrefixOp)) |prefix_op| {
|
if (opt.handle.tree.nodes.items(.tag)[opt_node] == .optional_type) {
|
||||||
if (opt_node.tag == .OptionalType) {
|
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
||||||
.node = prefix_op.rhs,
|
.node = opt.handle.tree.nodes.items(.data)[opt_node].lhs,
|
||||||
.handle = opt.handle,
|
.handle = opt.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -403,15 +400,12 @@ fn resolveUnwrapErrorType(
|
|||||||
},
|
},
|
||||||
.primitive, .slice, .pointer => return null,
|
.primitive, .slice, .pointer => return null,
|
||||||
};
|
};
|
||||||
|
if (rhs.handle.tree.nodes.items(.tag)[rhs_node] == .error_union) {
|
||||||
if (rhs_node.cast(ast.Node.SimpleInfixOp)) |infix_op| {
|
|
||||||
if (rhs_node.tag == .ErrorUnion) {
|
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
||||||
.node = infix_op.rhs,
|
.node = rhs.handle.tree.nodes.items(.data)[rhs_node].rhs,
|
||||||
.handle = rhs.handle,
|
.handle = rhs.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -470,32 +464,27 @@ fn resolveBracketAccessType(
|
|||||||
else => return null,
|
else => return null,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (lhs_node.castTag(.SliceType)) |slice_type| {
|
const tags = lhs.handle.tree.nodes.items(.tag);
|
||||||
|
const tag = tags[lhs_node];
|
||||||
|
const data = lhs.handle.tree.nodes.items(.data)[lhs_node];
|
||||||
|
if (tag == .array_type or tag == .array_type_sentinel) {
|
||||||
if (rhs == .Single)
|
if (rhs == .Single)
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
||||||
.node = slice_type.rhs,
|
.node = data.rhs,
|
||||||
.handle = lhs.handle,
|
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
|
||||||
return lhs;
|
|
||||||
} else if (lhs_node.castTag(.ArrayType)) |array_type| {
|
|
||||||
if (rhs == .Single)
|
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
|
||||||
.node = array_type.rhs,
|
|
||||||
.handle = lhs.handle,
|
.handle = lhs.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
return TypeWithHandle{
|
return TypeWithHandle{
|
||||||
.type = .{ .data = .{ .slice = array_type.rhs }, .is_type_val = false },
|
.type = .{ .data = .{ .slice = data.rhs }, .is_type_val = false },
|
||||||
.handle = lhs.handle,
|
.handle = lhs.handle,
|
||||||
};
|
};
|
||||||
} else if (lhs_node.castTag(.PtrType)) |ptr_type| {
|
} else if (isPtrType(tree, lhs_node)) {
|
||||||
if (ptr_type.rhs.castTag(.ArrayType)) |child_arr| {
|
if (tags[data.rhs] == .array_type or tags[data.rhs] == .array_type_sentinel) {
|
||||||
if (rhs == .Single) {
|
if (rhs == .Single) {
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
||||||
.node = child_arr.rhs,
|
.node = lhs.handle.tree.nodes.items(.data)[data.rhs].rhs,
|
||||||
.handle = lhs.handle,
|
.handle = lhs.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
}
|
}
|
||||||
return lhs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -931,28 +920,26 @@ pub const TypeWithHandle = struct {
|
|||||||
|
|
||||||
fn isRoot(self: TypeWithHandle) bool {
|
fn isRoot(self: TypeWithHandle) bool {
|
||||||
switch (self.type.data) {
|
switch (self.type.data) {
|
||||||
.other => |n| return n.tag == .Root,
|
// root is always index 0
|
||||||
|
.other => |n| return n == 0,
|
||||||
else => return false,
|
else => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isContainer(self: TypeWithHandle, container_kind_tok: std.zig.Token.Id) bool {
|
fn isContainer(self: TypeWithHandle, container_kind_tok: std.zig.Token.Tag, tree: ast.Tree) bool {
|
||||||
|
const main_tokens = tree.nodes.items(.main_token);
|
||||||
|
const tags = tree.tokens.items(.tag);
|
||||||
switch (self.type.data) {
|
switch (self.type.data) {
|
||||||
.other => |n| {
|
.other => |n| return tags[main_tokens[n]] == container_kind_tok,
|
||||||
if (n.castTag(.ContainerDecl)) |cont| {
|
|
||||||
return self.handle.tree.token_ids[cont.kind_token] == container_kind_tok;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
else => return false,
|
else => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isStructType(self: TypeWithHandle) bool {
|
pub fn isStructType(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
return self.isContainer(.Keyword_struct) or self.isRoot();
|
return self.isContainer(.keyword_struct, tree) or self.isRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isNamespace(self: TypeWithHandle) bool {
|
pub fn isNamespace(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
if (!self.isStructType()) return false;
|
if (!self.isStructType()) return false;
|
||||||
var idx: usize = 0;
|
var idx: usize = 0;
|
||||||
while (self.type.data.other.iterate(idx)) |child| : (idx += 1) {
|
while (self.type.data.other.iterate(idx)) |child| : (idx += 1) {
|
||||||
@ -962,46 +949,56 @@ pub const TypeWithHandle = struct {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isEnumType(self: TypeWithHandle) bool {
|
pub fn isEnumType(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
return self.isContainer(.Keyword_enum);
|
return self.isContainer(.keyword_enum, tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isUnionType(self: TypeWithHandle) bool {
|
pub fn isUnionType(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
return self.isContainer(.Keyword_union);
|
return self.isContainer(.keyword_union, tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isOpaqueType(self: TypeWithHandle) bool {
|
pub fn isOpaqueType(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
return self.isContainer(.Keyword_opaque);
|
return self.isContainer(.keyword_opaque, tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isTypeFunc(self: TypeWithHandle) bool {
|
pub fn isTypeFunc(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
|
var buf: [1]ast.Node.Index = undefined;
|
||||||
switch (self.type.data) {
|
switch (self.type.data) {
|
||||||
.other => |n| {
|
.other => |n| return switch (tree.nodes.items(.tag)[n]) {
|
||||||
if (n.castTag(.FnProto)) |fn_proto| {
|
.fn_proto => isTypeFunction(tree, tree.fnProto(n)),
|
||||||
return isTypeFunction(self.handle.tree, fn_proto);
|
.fn_proto_multi => isTypeFunction(tree, tree.fnProtoMulti(n)),
|
||||||
}
|
.fn_proto_one => isTypeFunction(tree, tree.fnProtoOne(&buf, n)),
|
||||||
return false;
|
.fn_proto_simple => isTypeFunction(tree, tree.fnProtoSimple(&buf, n)),
|
||||||
|
else => false,
|
||||||
},
|
},
|
||||||
else => return false,
|
else => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isGenericFunc(self: TypeWithHandle) bool {
|
pub fn isGenericFunc(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
|
var buf: [1]ast.Node.Index = undefined;
|
||||||
switch (self.type.data) {
|
switch (self.type.data) {
|
||||||
.other => |n| {
|
.other => |n| return switch (tree.nodes.items(.tag)[n]) {
|
||||||
if (n.castTag(.FnProto)) |fn_proto| {
|
.fn_proto => isGenericFunction(tree, tree.fnProto(n)),
|
||||||
return isGenericFunction(self.handle.tree, fn_proto);
|
.fn_proto_multi => isGenericFunction(tree, tree.fnProtoMulti(n)),
|
||||||
}
|
.fn_proto_one => isGenericFunction(tree, tree.fnProtoOne(&buf, n)),
|
||||||
return false;
|
.fn_proto_simple => isGenericFunction(tree, tree.fnProtoSimple(&buf, n)),
|
||||||
|
else => false,
|
||||||
},
|
},
|
||||||
else => return false,
|
else => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isFunc(self: TypeWithHandle) bool {
|
pub fn isFunc(self: TypeWithHandle, tree: ast.Tree) bool {
|
||||||
|
const tags = tree.nodes.items(.tag);
|
||||||
switch (self.type.data) {
|
switch (self.type.data) {
|
||||||
.other => |n| {
|
.other => |n| return switch (tags[n]) {
|
||||||
return n.tag == .FnProto;
|
.fn_proto,
|
||||||
|
.fn_proto_multi,
|
||||||
|
.fn_proto_one,
|
||||||
|
.fn_proto_simple,
|
||||||
|
=> true,
|
||||||
|
else => false,
|
||||||
},
|
},
|
||||||
else => return false,
|
else => return false,
|
||||||
}
|
}
|
||||||
@ -1100,7 +1097,7 @@ pub fn getFieldAccessType(
|
|||||||
},
|
},
|
||||||
.period => {
|
.period => {
|
||||||
const after_period = tokenizer.next();
|
const after_period = tokenizer.next();
|
||||||
switch (after_period.id) {
|
switch (after_period.tag) {
|
||||||
.Eof => return FieldAccessReturn{
|
.Eof => return FieldAccessReturn{
|
||||||
.original = current_type,
|
.original = current_type,
|
||||||
.unwrapped = try resolveDerefType(store, arena, current_type, &bound_type_params),
|
.unwrapped = try resolveDerefType(store, arena, current_type, &bound_type_params),
|
||||||
@ -1133,7 +1130,7 @@ pub fn getFieldAccessType(
|
|||||||
current_type = (try resolveUnwrapOptionalType(store, arena, current_type, &bound_type_params)) orelse return null;
|
current_type = (try resolveUnwrapOptionalType(store, arena, current_type, &bound_type_params)) orelse return null;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
log.debug("Unrecognized token {} after period.", .{after_period.id});
|
log.debug("Unrecognized token {} after period.", .{after_period.tag});
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1155,11 +1152,11 @@ pub fn getFieldAccessType(
|
|||||||
// Skip to the right paren
|
// Skip to the right paren
|
||||||
var paren_count: usize = 1;
|
var paren_count: usize = 1;
|
||||||
var next = tokenizer.next();
|
var next = tokenizer.next();
|
||||||
while (next.id != .Eof) : (next = tokenizer.next()) {
|
while (next.tag != .Eof) : (next = tokenizer.next()) {
|
||||||
if (next.id == .RParen) {
|
if (next.tag == .RParen) {
|
||||||
paren_count -= 1;
|
paren_count -= 1;
|
||||||
if (paren_count == 0) break;
|
if (paren_count == 0) break;
|
||||||
} else if (next.id == .LParen) {
|
} else if (next.tag == .LParen) {
|
||||||
paren_count += 1;
|
paren_count += 1;
|
||||||
}
|
}
|
||||||
} else return null;
|
} else return null;
|
||||||
@ -1170,13 +1167,13 @@ pub fn getFieldAccessType(
|
|||||||
var brack_count: usize = 1;
|
var brack_count: usize = 1;
|
||||||
var next = tokenizer.next();
|
var next = tokenizer.next();
|
||||||
var is_range = false;
|
var is_range = false;
|
||||||
while (next.id != .Eof) : (next = tokenizer.next()) {
|
while (next.tag != .Eof) : (next = tokenizer.next()) {
|
||||||
if (next.id == .RBracket) {
|
if (next.tag == .RBracket) {
|
||||||
brack_count -= 1;
|
brack_count -= 1;
|
||||||
if (brack_count == 0) break;
|
if (brack_count == 0) break;
|
||||||
} else if (next.id == .LBracket) {
|
} else if (next.tag == .LBracket) {
|
||||||
brack_count += 1;
|
brack_count += 1;
|
||||||
} else if (next.id == .Ellipsis2 and brack_count == 1) {
|
} else if (next.tag == .Ellipsis2 and brack_count == 1) {
|
||||||
is_range = true;
|
is_range = true;
|
||||||
}
|
}
|
||||||
} else return null;
|
} else return null;
|
||||||
@ -1664,10 +1661,10 @@ pub const Declaration = union(enum) {
|
|||||||
name: ast.TokenIndex,
|
name: ast.TokenIndex,
|
||||||
condition: ast.Node.Index,
|
condition: ast.Node.Index,
|
||||||
},
|
},
|
||||||
array_payload: struct {
|
// array_payload: struct {
|
||||||
identifier: *ast.Node,
|
// identifier: *ast.Node,
|
||||||
array_expr: ast.full.ArrayType,
|
// array_expr: ast.full.ArrayType,
|
||||||
},
|
// },
|
||||||
switch_payload: struct {
|
switch_payload: struct {
|
||||||
node: ast.TokenIndex,
|
node: ast.TokenIndex,
|
||||||
switch_expr: ast.Node.Index,
|
switch_expr: ast.Node.Index,
|
||||||
@ -1686,7 +1683,7 @@ pub const DeclWithHandle = struct {
|
|||||||
.ast_node => |n| getDeclNameToken(tree, n).?,
|
.ast_node => |n| getDeclNameToken(tree, n).?,
|
||||||
.param_decl => |p| p.name_token.?,
|
.param_decl => |p| p.name_token.?,
|
||||||
.pointer_payload => |pp| pp.node.value_symbol.firstToken(),
|
.pointer_payload => |pp| pp.node.value_symbol.firstToken(),
|
||||||
.array_payload => |ap| ap.identifier.firstToken(),
|
// .array_payload => |ap| ap.identifier.firstToken(),
|
||||||
.switch_payload => |sp| sp.node.value_symbol.firstToken(),
|
.switch_payload => |sp| sp.node.value_symbol.firstToken(),
|
||||||
.label_decl => |ld| ld.firstToken(),
|
.label_decl => |ld| ld.firstToken(),
|
||||||
};
|
};
|
||||||
@ -1705,31 +1702,31 @@ 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, arena: *std.heap.ArenaAllocator, 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.*) {
|
return switch (self.decl.*) {
|
||||||
.ast_node => |node| try resolveTypeOfNodeInternal(store, arena, .{ .node = node, .handle = self.handle }, bound_type_params),
|
.ast_node => |node| try resolveTypeOfNodeInternal(store, arena, .{ .node = node, .handle = self.handle }, bound_type_params),
|
||||||
.param_decl => |param_decl| switch (param_decl.param_type) {
|
.param_decl => |*param_decl| {
|
||||||
.type_expr => |type_node| {
|
if (typeIsType(self.handle.tree, param_decl.type_expr)) {
|
||||||
if (typeIsType(self.handle.tree, type_node)) {
|
|
||||||
var bound_param_it = bound_type_params.iterator();
|
var bound_param_it = bound_type_params.iterator();
|
||||||
while (bound_param_it.next()) |entry| {
|
while (bound_param_it.next()) |entry| {
|
||||||
if (entry.key == param_decl) return entry.value;
|
if (entry.key == param_decl) return entry.value;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else if (type_node.castTag(.Identifier)) |type_ident| {
|
} else if (node_tags[param_decl.type_expr] == .identifier) {
|
||||||
if (param_decl.name_token) |name_tok| {
|
if (param_decl.name_token) |name_tok| {
|
||||||
if (std.mem.eql(u8, self.handle.tree.tokenSlice(type_ident.firstToken()), self.handle.tree.tokenSlice(name_tok)))
|
if (std.mem.eql(u8, tree.tokenSlice(tree.firstToken(param_decl.type_expr)), tree.tokenSlice(name_tok)))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ((try resolveTypeOfNodeInternal(
|
return ((try resolveTypeOfNodeInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
arena,
|
||||||
.{ .node = type_node, .handle = self.handle },
|
.{ .node = param_decl.type_expr, .handle = self.handle },
|
||||||
bound_type_params,
|
bound_type_params,
|
||||||
)) orelse return null).instanceTypeVal();
|
)) orelse return null).instanceTypeVal();
|
||||||
},
|
},
|
||||||
else => null,
|
|
||||||
},
|
|
||||||
.pointer_payload => |pay| try resolveUnwrapOptionalType(
|
.pointer_payload => |pay| try resolveUnwrapOptionalType(
|
||||||
store,
|
store,
|
||||||
arena,
|
arena,
|
||||||
@ -1739,16 +1736,16 @@ pub const DeclWithHandle = struct {
|
|||||||
}, bound_type_params)) orelse return null,
|
}, bound_type_params)) orelse return null,
|
||||||
bound_type_params,
|
bound_type_params,
|
||||||
),
|
),
|
||||||
.array_payload => |pay| try resolveBracketAccessType(
|
// .array_payload => |pay| try resolveBracketAccessType(
|
||||||
store,
|
// store,
|
||||||
arena,
|
// arena,
|
||||||
(try resolveTypeOfNodeInternal(store, arena, .{
|
// (try resolveTypeOfNodeInternal(store, arena, .{
|
||||||
.node = pay.array_expr,
|
// .node = pay.array_expr,
|
||||||
.handle = self.handle,
|
// .handle = self.handle,
|
||||||
}, bound_type_params)) orelse return null,
|
// }, bound_type_params)) orelse return null,
|
||||||
.Single,
|
// .Single,
|
||||||
bound_type_params,
|
// bound_type_params,
|
||||||
),
|
// ),
|
||||||
.label_decl => return null,
|
.label_decl => return null,
|
||||||
.switch_payload => |pay| {
|
.switch_payload => |pay| {
|
||||||
if (pay.items.len == 0) return null;
|
if (pay.items.len == 0) return null;
|
||||||
@ -1757,20 +1754,20 @@ pub const DeclWithHandle = struct {
|
|||||||
.node = pay.switch_expr,
|
.node = pay.switch_expr,
|
||||||
.handle = self.handle,
|
.handle = self.handle,
|
||||||
}, bound_type_params)) orelse return null;
|
}, bound_type_params)) orelse return null;
|
||||||
if (!switch_expr_type.isUnionType())
|
if (!switch_expr_type.isUnionType(tree))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (pay.items[0].castTag(.EnumLiteral)) |enum_lit| {
|
if (node_tags[pay.items[0]] == .enum_literal) {
|
||||||
const scope = findContainerScope(.{ .node = switch_expr_type.type.data.other, .handle = switch_expr_type.handle }) orelse return null;
|
const scope = findContainerScope(.{ .node = switch_expr_type.type.data.other, .handle = switch_expr_type.handle }) orelse return null;
|
||||||
if (scope.decls.getEntry(self.handle.tree.tokenSlice(enum_lit.name))) |candidate| {
|
if (scope.decls.getEntry(self.handle.tree.tokenSlice(main_tokens[pay.items[0]]))) |candidate| {
|
||||||
switch (candidate.value) {
|
switch (candidate.value) {
|
||||||
.ast_node => |node| {
|
.ast_node => |node| {
|
||||||
if (node.castTag(.ContainerField)) |container_field| {
|
if (containerField(tree, node)) |container_field| {
|
||||||
if (container_field.type_expr) |type_expr| {
|
if (container_field.ast.type_expr != 0) {
|
||||||
return ((try resolveTypeOfNodeInternal(
|
return ((try resolveTypeOfNodeInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
arena,
|
||||||
.{ .node = type_expr, .handle = switch_expr_type.handle },
|
.{ .node = container_field.ast.type_expr, .handle = switch_expr_type.handle },
|
||||||
bound_type_params,
|
bound_type_params,
|
||||||
)) orelse return null).instanceTypeVal();
|
)) orelse return null).instanceTypeVal();
|
||||||
}
|
}
|
||||||
@ -1787,6 +1784,15 @@ pub const DeclWithHandle = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn containerField(tree: ast.Tree, node: ast.Node.Index) ?ast.full.ContainerField {
|
||||||
|
return switch (tree.nodes.items(.tag)[node]) {
|
||||||
|
.container_field => tree.containerField(node),
|
||||||
|
.container_field_init => tree.containerFieldInit(node),
|
||||||
|
.container_field_align => tree.containerFieldAlign(node),
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn findContainerScope(container_handle: NodeWithHandle) ?*Scope {
|
fn findContainerScope(container_handle: NodeWithHandle) ?*Scope {
|
||||||
const container = container_handle.node;
|
const container = container_handle.node;
|
||||||
const handle = container_handle.handle;
|
const handle = container_handle.handle;
|
||||||
|
Loading…
Reference in New Issue
Block a user