Skip to content

Commit b244a79

Browse files
Resolve type of enum literal for union tag
1 parent ad00b77 commit b244a79

8 files changed

Lines changed: 57 additions & 24 deletions

File tree

src/analysis.zig

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,8 +2830,8 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
28302830
defer analyser.arena.free(lineage);
28312831

28322832
const tag = offsets.identifierTokenToNameSlice(tree, tree.nodeMainToken(node));
2833-
const decl = (try analyser.lookupSymbolFieldInit(handle, tag, node, lineage[1..])) orelse return Type.fromIP(analyser, .enum_literal_type, null);
2834-
return decl.resolveType(analyser);
2833+
const decl, const type_maybe = (try analyser.lookupSymbolFieldInit(handle, tag, node, lineage[1..])) orelse return Type.fromIP(analyser, .enum_literal_type, null);
2834+
return type_maybe orelse decl.resolveType(analyser);
28352835
},
28362836

28372837
.unreachable_literal => return Type.fromIP(analyser, .noreturn_type, null),
@@ -6338,7 +6338,7 @@ pub fn lookupSymbolFieldInit(
63386338
field_name: []const u8,
63396339
node: Ast.Node.Index,
63406340
ancestors: []const Ast.Node.Index,
6341-
) Error!?DeclWithHandle {
6341+
) Error!?struct { DeclWithHandle, ?Type } {
63426342
var container_type = (try analyser.resolveExpressionType(
63436343
handle,
63446344
node,
@@ -6365,13 +6365,22 @@ pub fn lookupSymbolFieldInit(
63656365
container_type = try container_type.instanceUnchecked(analyser);
63666366

63676367
if (is_struct_init) {
6368-
return try container_type.lookupSymbol(analyser, field_name);
6368+
const decl = try container_type.lookupSymbol(analyser, field_name) orelse return null;
6369+
return .{ decl, null };
6370+
}
6371+
6372+
switch (container_type.data) {
6373+
.union_tag => |t| {
6374+
const decl = try t.lookupSymbol(analyser, field_name) orelse return null;
6375+
return .{ decl, container_type };
6376+
},
6377+
else => {},
63696378
}
63706379

63716380
switch (container_type.getContainerKind() orelse return null) {
63726381
.keyword_struct, .keyword_opaque => {},
6373-
.keyword_enum => if (try (try container_type.typeOf(analyser)).lookupSymbol(analyser, field_name)) |ty| return ty,
6374-
.keyword_union => if (try container_type.lookupSymbol(analyser, field_name)) |ty| return ty,
6382+
.keyword_enum => if (try (try container_type.typeOf(analyser)).lookupSymbol(analyser, field_name)) |decl| return .{ decl, null },
6383+
.keyword_union => if (try container_type.lookupSymbol(analyser, field_name)) |decl| return .{ decl, null },
63756384
else => return null,
63766385
}
63776386

@@ -6382,7 +6391,7 @@ pub fn lookupSymbolFieldInit(
63826391
resolved_type = try resolved_type.typeOf(analyser);
63836392
resolved_type = resolved_type.resolveDeclLiteralResultType();
63846393
resolved_type = try resolved_type.instanceUnchecked(analyser);
6385-
if (resolved_type.eql(container_type)) return decl;
6394+
if (resolved_type.eql(container_type)) return .{ decl, null };
63866395
return null;
63876396
}
63886397

@@ -6425,8 +6434,9 @@ pub fn resolveExpressionTypeFromAncestors(
64256434
const field_name_token = tree.firstToken(node) - 2;
64266435
if (tree.tokenTag(field_name_token) != .identifier) return null;
64276436
const field_name = offsets.identifierTokenToNameSlice(tree, field_name_token);
6428-
if (try analyser.lookupSymbolFieldInit(handle, field_name, ancestors[0], ancestors[1..])) |field_decl| {
6429-
return try field_decl.resolveType(analyser);
6437+
if (try analyser.lookupSymbolFieldInit(handle, field_name, ancestors[0], ancestors[1..])) |field| {
6438+
const decl, const type_maybe = field;
6439+
return type_maybe orelse try decl.resolveType(analyser);
64306440
}
64316441
}
64326442
},
@@ -6568,8 +6578,8 @@ pub fn resolveExpressionTypeFromAncestors(
65686578

65696579
var fn_type = if (tree.nodeTag(call.ast.fn_expr) == .enum_literal) blk: {
65706580
const field_name = offsets.identifierTokenToNameSlice(tree, tree.nodeMainToken(call.ast.fn_expr));
6571-
const decl = try analyser.lookupSymbolFieldInit(handle, field_name, call.ast.fn_expr, ancestors) orelse return null;
6572-
const ty = try decl.resolveType(analyser) orelse return null;
6581+
const decl, const type_maybe = try analyser.lookupSymbolFieldInit(handle, field_name, call.ast.fn_expr, ancestors) orelse return null;
6582+
const ty = type_maybe orelse try decl.resolveType(analyser) orelse return null;
65736583
break :blk try analyser.resolveFuncProtoOfCallable(ty) orelse return null;
65746584
} else blk: {
65756585
const ty = try analyser.resolveTypeOfNode(.of(call.ast.fn_expr, handle)) orelse return null;
@@ -6829,7 +6839,7 @@ pub fn getSymbolEnumLiteral(
68296839
handle: *DocumentStore.Handle,
68306840
source_index: usize,
68316841
name: []const u8,
6832-
) Error!?DeclWithHandle {
6842+
) Error!?struct { DeclWithHandle, ?Type } {
68336843
const tracy_zone = tracy.trace(@src());
68346844
defer tracy_zone.end();
68356845

src/features/goto.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ fn gotoDefinitionEnumLiteral(
149149
return gotoDefinitionStructInit(analyser, handle, source_index, kind, offset_encoding);
150150
};
151151
const name = offsets.locToSlice(handle.tree.source, name_loc);
152-
const decl = (try analyser.getSymbolEnumLiteral(handle, source_index, name)) orelse return null;
152+
const decl, _ = (try analyser.getSymbolEnumLiteral(handle, source_index, name)) orelse return null;
153153
return try gotoDefinitionSymbol(analyser, offsets.tokenToRange(&handle.tree, name_token, offset_encoding), decl, kind, offset_encoding);
154154
}
155155

src/features/hover.zig

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,24 @@ fn hoverSymbol(
1818
arena: std.mem.Allocator,
1919
param_decl_handle: Analyser.DeclWithHandle,
2020
markup_kind: types.MarkupKind,
21+
) Analyser.Error!?[]const u8 {
22+
return try hoverSymbolWithType(analyser, arena, param_decl_handle, null, markup_kind);
23+
}
24+
25+
fn hoverSymbolWithType(
26+
analyser: *Analyser,
27+
arena: std.mem.Allocator,
28+
param_decl_handle: Analyser.DeclWithHandle,
29+
type_maybe: ?Analyser.Type,
30+
markup_kind: types.MarkupKind,
2131
) Analyser.Error!?[]const u8 {
2232
const tracy_zone = tracy.trace(@src());
2333
defer tracy_zone.end();
2434

2535
var doc_strings: std.ArrayList([]const u8) = .empty;
2636

2737
var decl_handle: Analyser.DeclWithHandle = param_decl_handle;
28-
var maybe_resolved_type = try param_decl_handle.resolveType(analyser);
38+
var maybe_resolved_type = type_maybe orelse try param_decl_handle.resolveType(analyser);
2939

3040
while (true) {
3141
if (try decl_handle.docComments(arena)) |doc_string| {
@@ -380,13 +390,13 @@ fn hoverDefinitionEnumLiteral(
380390
return try hoverDefinitionStructInit(analyser, arena, handle, source_index, markup_kind, offset_encoding);
381391
};
382392
const name = offsets.locToSlice(handle.tree.source, name_loc);
383-
const decl = (try analyser.getSymbolEnumLiteral(handle, source_index, name)) orelse return null;
393+
const decl, const type_maybe = (try analyser.getSymbolEnumLiteral(handle, source_index, name)) orelse return null;
384394

385395
return .{
386396
.contents = .{
387397
.markup_content = .{
388398
.kind = markup_kind,
389-
.value = (try hoverSymbol(analyser, arena, decl, markup_kind)) orelse return null,
399+
.value = (try hoverSymbolWithType(analyser, arena, decl, type_maybe, markup_kind)) orelse return null,
390400
},
391401
},
392402
.range = offsets.tokenToRange(&handle.tree, name_token, offset_encoding),

src/features/inlay_hints.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,8 @@ fn writeNodeInlayHint(
520520
const name_token = tree.firstToken(value_node) - 2; // math our way two token indexes back to get the `name`
521521
const name_loc = offsets.tokenToLoc(tree, name_token);
522522
const name = offsets.locToSlice(tree.source, name_loc);
523-
const decl = (try builder.analyser.getSymbolEnumLiteral(builder.handle, name_loc.start, name)) orelse continue;
524-
const ty = try decl.resolveType(builder.analyser) orelse continue;
523+
const decl, const type_maybe = (try builder.analyser.getSymbolEnumLiteral(builder.handle, name_loc.start, name)) orelse continue;
524+
const ty = type_maybe orelse try decl.resolveType(builder.analyser) orelse continue;
525525
const type_str = try ty.stringifyTypeOf(builder.analyser, .{ .truncate_container_decls = true });
526526
if (type_str.len == 0) continue;
527527
try appendTypeHintString(

src/features/references.zig

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ const Builder = struct {
186186
else => unreachable,
187187
};
188188

189-
const candidate = try builder.analyser.lookupSymbolFieldInit(
189+
const candidate, _ = try builder.analyser.lookupSymbolFieldInit(
190190
handle,
191191
name,
192192
nodes[0],
@@ -204,7 +204,7 @@ const Builder = struct {
204204
const name_token = tree.nodeMainToken(node);
205205
const name = offsets.identifierTokenToNameSlice(&handle.tree, name_token);
206206
if (!std.mem.eql(u8, name, target_symbol_name)) return;
207-
const candidate = try builder.analyser.getSymbolEnumLiteral(handle, tree.tokenStart(name_token), name) orelse return;
207+
const candidate, _ = try builder.analyser.getSymbolEnumLiteral(handle, tree.tokenStart(name_token), name) orelse return;
208208
break :candidate .{ candidate, name_token };
209209
},
210210
.global_var_decl,
@@ -728,7 +728,10 @@ pub fn referencesHandler(server: *Server, arena: std.mem.Allocator, request: Gen
728728
break :z null;
729729
},
730730
.label_access, .label_decl => try Analyser.lookupLabel(handle, name, source_index),
731-
.enum_literal => try analyser.getSymbolEnumLiteral(handle, source_index, name),
731+
.enum_literal => blk: {
732+
const decl, _ = try analyser.getSymbolEnumLiteral(handle, source_index, name) orelse break :blk null;
733+
break :blk decl;
734+
},
732735
.keyword => null,
733736
else => null,
734737
} orelse return null;

src/features/signature_help.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,12 @@ pub fn getSignatureInfo(
266266
var ty = switch (tree.tokenTag(expr_first_token)) {
267267
.period => blk: { // decl literal
268268
loc.start += 1;
269-
const decl = try analyser.getSymbolEnumLiteral(
269+
const decl, const type_maybe = try analyser.getSymbolEnumLiteral(
270270
handle,
271271
loc.start,
272272
offsets.locToSlice(tree.source, loc),
273273
) orelse continue;
274-
break :blk try decl.resolveType(analyser) orelse continue;
274+
break :blk type_maybe orelse try decl.resolveType(analyser) orelse continue;
275275
},
276276
else => try analyser.getFieldAccessType(handle, loc.start, loc) orelse continue,
277277
};

tests/analysis/meta.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ const TagA = std.meta.Tag(TaggedUnionA);
2121
const TagB = std.meta.Tag(TaggedUnionB);
2222
// ^^^^ (type)(@typeInfo(TaggedUnionB).@"union".tag_type.?)
2323

24+
const tag_a: TagA = .foo;
25+
// ^^^^ (EnumA)()
26+
27+
const tag_b: TagB = .fizz;
28+
// ^^^^^ (@typeInfo(TaggedUnionB).@"union".tag_type.?)()
29+
2430
const ArgsTupleA = std.meta.ArgsTuple(fn (u8, i32) void);
2531
// ^^^^^^^^^^ (type)(struct { u8, i32 })
2632

tests/analysis_check.zig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,11 @@ pub fn main(init: std.process.Init) Error!void {
190190
const ty = blk: {
191191
const decl_maybe = switch (ctx) {
192192
.global => try analyser.lookupSymbolGlobal(handle, identifier, identifier_loc.start),
193-
.enum_literal => try analyser.getSymbolEnumLiteral(handle, identifier_loc.start, identifier),
193+
.enum_literal => decl: {
194+
const decl, const type_maybe = try analyser.getSymbolEnumLiteral(handle, identifier_loc.start, identifier) orelse break :decl null;
195+
if (type_maybe) |ty| break :blk ty;
196+
break :decl decl;
197+
},
194198
.struct_init => break :blk try analyser.resolveStructInitType(handle, identifier_loc.start),
195199
};
196200

0 commit comments

Comments
 (0)