Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/analyser/InternPool.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3155,6 +3155,17 @@ pub fn isType(ip: *InternPool, ty: Index) bool {
};
}

pub fn isUndefined(ip: *InternPool, index: Index) bool {
switch (index) {
.undefined_value => return true,
else => {
ip.lock.lockSharedUncancelable(ip.io);
defer ip.lock.unlockShared(ip.io);
return ip.items.items(.tag)[@intFromEnum(index)] == .undefined_value;
},
}
}

pub fn isUnknown(ip: *InternPool, index: Index) bool {
switch (index) {
.unknown_type, .unknown_unknown => return true,
Expand Down
52 changes: 49 additions & 3 deletions src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,28 @@ fn resolveOptionalIPValue(
return try analyser.resolveInternPoolValue(.of(node, handle)) orelse .unknown_unknown;
}

fn resolveCoercedIPValue(
analyser: *Analyser,
ip_ty: InternPool.Index,
options: ResolveOptions,
) Error!?InternPool.Index {
if (!analyser.ip.isType(ip_ty)) return null;
const ty = try analyser.resolveTypeOfNode(options) orelse return null;
const ip_index = ty.ipIndex() orelse return null;
if (analyser.ip.isUndefined(ip_index)) return null;

var arena_allocator: std.heap.ArenaAllocator = .init(analyser.gpa);
defer arena_allocator.deinit();
const arena = arena_allocator.allocator();

var err_msg: ErrorMsg = undefined;
const new_index = try analyser.ip.coerce(arena, ip_ty, ip_index, builtin.target, &err_msg);

if (new_index == .none) return null;
if (analyser.ip.isUnknown(new_index)) return null;
return new_index;
}

fn resolveInternPoolValue(analyser: *Analyser, options: ResolveOptions) Error!?InternPool.Index {
const old_resolve_number_literal_values = analyser.resolve_number_literal_values;
analyser.resolve_number_literal_values = true;
Expand Down Expand Up @@ -1968,6 +1990,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
.aligned_var_decl,
=> {
const var_decl = tree.fullVarDecl(node).?;
const mut_token_tag = tree.tokenTag(var_decl.ast.mut_token);
var fallback_type: ?Type = null;

if (var_decl.ast.type_node.unwrap()) |type_node| blk: {
Expand All @@ -1979,11 +2002,20 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
fallback_type = .unknown_type;
break :blk;
}
if (mut_token_tag == .keyword_const) num: {
const init_node = var_decl.ast.init_node.unwrap() orelse break :num;
const ip_ty = decl_type.ipIndex() orelse break :num;
const ip_index = try analyser.resolveCoercedIPValue(ip_ty, .of(init_node, handle)) orelse break :num;
return Type.fromIP(analyser, analyser.ip.typeOf(ip_index), ip_index);
}
return try decl_type.instanceTypeVal(analyser);
}

if (var_decl.ast.init_node.unwrap()) |init_node| blk: {
return try analyser.resolveTypeOfNodeInternal(.of(init_node, handle)) orelse break :blk;
const ty = try analyser.resolveTypeOfNodeInternal(.of(init_node, handle)) orelse break :blk;
if (mut_token_tag == .keyword_var)
return ty.withoutIPIndex(analyser);
return ty;
}

return fallback_type;
Expand Down Expand Up @@ -2275,7 +2307,17 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
if (params.len != 0) return null;
return options.container_type orelse try analyser.innermostContainer(handle, tree.tokenStart(tree.firstToken(node)));
},
.as,
.as => {
if (params.len < 1) return null;
const ty = (try analyser.resolveTypeOfNodeInternal(.of(params[0], handle))) orelse return null;
num: {
if (params.len < 2) break :num;
const ip_ty = ty.ipIndex() orelse break :num;
const ip_index = try analyser.resolveCoercedIPValue(ip_ty, .of(params[1], handle)) orelse break :num;
return Type.fromIP(analyser, analyser.ip.typeOf(ip_index), ip_index);
}
return try ty.instanceTypeVal(analyser);
},
.atomic_load,
.atomic_rmw,
.@"extern",
Expand Down Expand Up @@ -2709,7 +2751,11 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
.bit_not,
.negation,
.negation_wrap,
=> return try analyser.resolveTypeOfNodeInternal(.of(tree.nodeData(node).node, handle)),
=> {
const ty = try analyser.resolveTypeOfNodeInternal(.of(tree.nodeData(node).node, handle)) orelse return null;
if (ty.is_type_val) return null;
return ty.withoutIPIndex(analyser);
},

.multiline_string_literal => {
const start, const end = tree.nodeData(node).token_and_token;
Expand Down
13 changes: 11 additions & 2 deletions tests/analysis/integer_literal.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,23 @@ const comptime_shl = 2 << 3;
const one_plus_one = 1 + 1;
// ^^^^^^^^^^^^ (comptime_int)((unknown value)) TODO this should be `2`

const negation_one = -1;
// ^^^^^^^^^^^^ (comptime_int)((unknown value)) TODO this should be `-1`

const negation_wrap_one = -%1;
// ^^^^^^^^^^^^^^^^^ (comptime_int)((unknown value)) TODO this should be `-1`

const bit_not_one = ~1;
// ^^^^^^^^^^^ (comptime_int)((unknown value))

const const_u8: u8 = 42;
// ^^^^^^^^ (u8)((unknown value)) TODO this should be `42`
// ^^^^^^^^ (u8)(42)

var var_u8: u8 = 42;
// ^^^^^^ (u8)((unknown value))

const as_u8 = @as(u8, 42);
// ^^^^^ (u8)((unknown value)) TODO this should be `42`
// ^^^^^ (u8)(42)

const as_u8_too_big = @as(u8, 256);
// ^^^^^^^^^^^^^ (u8)((unknown value))
Expand Down
3 changes: 3 additions & 0 deletions tests/analysis/variable.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const variable addrspace(.generic) linksection(.{}) = 0;
// ^^^^^^^^ (AddressSpace)()
// ^ ([]const u8)()

var bool_var = true;
// ^^^^^^^^ (bool)((unknown value))
2 changes: 1 addition & 1 deletion tests/lsp_features/hover.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ test "alias with different type" {
\\const bar<cursor>: ?i32 = foo;
,
\\const foo: i32 = 1
\\(?i32)
\\(?i32 = 1)
, .{ .markup_kind = .plaintext });
}

Expand Down
Loading