Skip to content

Commit

Permalink
Fix type resolution for MyTaggedUnion.value
Browse files Browse the repository at this point in the history
  • Loading branch information
FnControlOption committed Jul 18, 2023
1 parent 9cedc7c commit 165b8bf
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 6 deletions.
93 changes: 90 additions & 3 deletions src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,9 @@ pub fn resolveVarDeclAlias(analyser: *Analyser, node_handle: NodeWithHandle) err
.field_access => blk: {
const lhs = datas[node_handle.node].lhs;
const resolved = (try analyser.resolveTypeOfNode(.{ .node = lhs, .handle = handle })) orelse return null;
if (!resolved.type.is_type_val)
return null;

const resolved_node = switch (resolved.type.data) {
.other => |n| n,
else => return null,
Expand Down Expand Up @@ -604,7 +607,7 @@ fn resolveUnwrapErrorUnionType(analyser: *Analyser, rhs: TypeWithHandle, side: E
.left => null,
.right => t.*,
},
.primitive, .slice, .pointer, .multi_pointer, .array_index, .@"comptime", .either => return null,
else => return null,
};

if (rhs.handle.tree.nodes.items(.tag)[rhs_node] == .error_union) {
Expand All @@ -621,6 +624,56 @@ fn resolveUnwrapErrorUnionType(analyser: *Analyser, rhs: TypeWithHandle, side: E
return null;
}

fn resolveTaggedUnionFieldType(analyser: *Analyser, type_handle: TypeWithHandle, symbol: []const u8) !?TypeWithHandle {
if (!type_handle.type.is_type_val)
return null;

const node = switch (type_handle.type.data) {
.other => |n| n,
else => return null,
};

if (node == 0)
return null;

const handle = type_handle.handle;
const tree = handle.tree;
const node_tags = tree.nodes.items(.tag);
const token_tags = tree.tokens.items(.tag);

var buf: [2]Ast.Node.Index = undefined;
const container_decl = tree.fullContainerDecl(&buf, node) orelse
return null;

if (token_tags[container_decl.ast.main_token] != .keyword_union)
return null;

const child = try type_handle.lookupSymbol(analyser, symbol) orelse
return null;

if (child.decl.* != .ast_node or !node_tags[child.decl.ast_node].isContainerField())
return try child.resolveType(analyser);

if (container_decl.ast.enum_token != null) {
const union_type_ptr = try analyser.arena.allocator().create(TypeWithHandle);
union_type_ptr.* = type_handle;
return TypeWithHandle{
.type = .{ .data = .{ .union_tag = union_type_ptr }, .is_type_val = false },
.handle = handle,
};
}

if (container_decl.ast.arg != 0) {
const tag_type = (try analyser.resolveTypeOfNode(.{
.node = container_decl.ast.arg,
.handle = handle,
})) orelse return null;
return tag_type.instanceTypeVal();
}

return null;
}

/// Resolves the child type of a deref type
fn resolveDerefType(analyser: *Analyser, deref: TypeWithHandle) !?TypeWithHandle {
const deref_node = switch (deref.type.data) {
Expand Down Expand Up @@ -1218,11 +1271,14 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
.handle = handle,
})) orelse return null;

const symbol = tree.tokenSlice(datas[node].rhs);

if (try analyser.resolveTaggedUnionFieldType(lhs, symbol)) |tag_type|
return tag_type;

// If we are accessing a pointer type, remove one pointerness level :)
const left_type = (try analyser.resolveDerefType(lhs)) orelse lhs;

const symbol = tree.tokenSlice(datas[node].rhs);

if (try analyser.resolvePropertyType(left_type, symbol)) |t|
return t;

Expand Down Expand Up @@ -1490,14 +1546,38 @@ pub const Type = struct {
};

data: union(enum) {
/// Type of `foo` in `&foo`
pointer: *TypeWithHandle,

/// Element type of `slice` in `slice.ptr`
multi_pointer: *TypeWithHandle,

/// Element type of `array` in `array[x..y]`
slice: *TypeWithHandle,

/// Return type of `fn foo() !Foo`
error_union: *TypeWithHandle,

/// `Foo` in `Foo.bar` where `Foo = union(enum) { bar }`
union_tag: *TypeWithHandle,

/// - Container type: `struct {}`, `enum {}`, `union {}`, `opaque {}`, `error {}`
/// - Pointer type: `*Foo`, `[]Foo`, `?Foo`
/// - Error type: `Foo || Bar`, `Foo!Bar`
/// - Function: `fn () Foo`, `fn foo() Foo`
/// - Literal: `"foo"`, `'x'`, `42`, `.foo`, `error.Foo`
/// - Primitive value: `true`, `false`, `null`, `undefined`
other: Ast.Node.Index,

/// Primitive type: `u8`, `bool`, `type`, etc.
primitive: []const u8,

/// Branching types
either: []const EitherEntry,

// TODO: Unused?
array_index,

@"comptime": struct {
interpreter: *ComptimeInterpreter,
value: ComptimeInterpreter.Value,
Expand All @@ -1523,6 +1603,7 @@ pub const TypeWithHandle = struct {
.multi_pointer,
.slice,
.error_union,
.union_tag,
=> |t| hashTypeWithHandle(hasher, t.*),
.other => |idx| hasher.update(&std.mem.toBytes(idx)),
.primitive => |name| hasher.update(name),
Expand Down Expand Up @@ -1561,6 +1642,7 @@ pub const TypeWithHandle = struct {
.multi_pointer,
.slice,
.error_union,
.union_tag,
=> |a_type, name| {
const b_type = @field(b.type.data, @tagName(name));
if (!self.eql(a_type.*, b_type.*)) return false;
Expand Down Expand Up @@ -4163,6 +4245,11 @@ fn addReferencedTypes(
return try std.fmt.allocPrint(allocator, "!{s}", .{rhs_str orelse return null});
},

.union_tag => |t| {
const union_type_str = try analyser.addReferencedTypes(t.*, ReferencedType.Collector.init(referenced_types));
return try std.fmt.allocPrint(allocator, "@typeInfo({s}).Union.tag_type.?", .{union_type_str orelse return null});
},

.other => |p| switch (node_tags[p]) {
.root => {
const path = URI.parse(allocator, handle.uri) catch |err| switch (err) {
Expand Down
4 changes: 1 addition & 3 deletions src/features/completions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ fn typeToCompletion(
});
}
},
.error_union => {},
.multi_pointer => {},
.pointer => |t| {
if (server.config.operator_completions) {
try list.append(arena, .{
Expand All @@ -74,7 +72,6 @@ fn typeToCompletion(
null,
either_descriptor,
),
.primitive, .array_index => {},
.@"comptime" => |co| try analyser_completions.dotCompletions(
arena,
list,
Expand All @@ -87,6 +84,7 @@ fn typeToCompletion(
for (bruh) |a|
try typeToCompletion(server, analyser, arena, list, .{ .original = a.type_with_handle }, orig_handle, a.descriptor);
},
else => {},
}
}

Expand Down

0 comments on commit 165b8bf

Please sign in to comment.