Skip to content
Open
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
87 changes: 73 additions & 14 deletions src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ pub fn resolveOrelseType(analyser: *Analyser, lhs: Type, rhs: Type) error{OutOfM

pub fn resolveAddressOf(analyser: *Analyser, is_const: bool, ty: Type) error{OutOfMemory}!Type {
const elem_ty = try ty.typeOf(analyser);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, is_const, elem_ty);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, is_const, false, false, 0, .generic, elem_ty);
return try pointer_ty.instanceUnchecked(analyser);
}

Expand Down Expand Up @@ -1231,12 +1231,12 @@ pub fn resolveBracketAccess(analyser: *Analyser, lhs_binding: Binding, rhs: Brac
switch (result) {
.array => |elem_count| {
const array_ty = try Type.createArrayType(analyser, elem_count, sentinel, elem_ty.*);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, is_const, array_ty);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, is_const, false, false, 0, .generic, array_ty);
const pointer_instance = try pointer_ty.instanceUnchecked(analyser);
return .{ .type = pointer_instance, .is_const = true };
},
.slice => {
const slice_ty = try Type.createPointerType(analyser, .slice, sentinel, is_const, elem_ty.*);
const slice_ty = try Type.createPointerType(analyser, .slice, sentinel, is_const, false, false, 0, .generic, elem_ty.*);
const slice_instance = try slice_ty.instanceUnchecked(analyser);
return .{ .type = slice_instance, .is_const = true };
},
Expand Down Expand Up @@ -2153,13 +2153,30 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
const ptr_info = ast.fullPtrType(tree, node).?;
const size = ptr_info.size;
const is_const = ptr_info.const_token != null;
const is_volatile = ptr_info.volatile_token != null;
const is_allowzero = ptr_info.allowzero_token != null;

const sentinel = try analyser.resolveOptionalIPValue(ptr_info.ast.sentinel, handle);

const alignment: u16 = if (ptr_info.ast.align_node.unwrap()) |align_node|
try analyser.resolveIntegerLiteral(u16, .of(align_node, handle)) orelse 0
else
0;

const elem_ty = try analyser.resolveTypeOfNodeInternal(.of(ptr_info.ast.child_type, handle)) orelse return null;
if (!elem_ty.is_type_val) return null;

return try Type.createPointerType(analyser, size, sentinel, is_const, elem_ty);
return try Type.createPointerType(
analyser,
size,
sentinel,
is_const,
is_volatile,
is_allowzero,
alignment,
.generic,
elem_ty,
);
},
.array_type,
.array_type_sentinel,
Expand Down Expand Up @@ -2957,7 +2974,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
elem_ty = try elem_ty.instanceUnchecked(analyser);
elem_ty = try analyser.resolveArrayMult(elem_ty, mult_lit) orelse return null;
elem_ty = try elem_ty.typeOf(analyser);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, true, elem_ty);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, true, false, false, 0, .generic, elem_ty);
return try pointer_ty.instanceUnchecked(analyser);
}

Expand All @@ -2979,7 +2996,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
r_elem_ty = try r_elem_ty.instanceUnchecked(analyser);
var elem_ty = try analyser.resolveArrayCat(l_elem_ty, r_elem_ty) orelse return null;
elem_ty = try elem_ty.typeOf(analyser);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, true, elem_ty);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, true, false, false, 0, .generic, elem_ty);
return try pointer_ty.instanceUnchecked(analyser);
}

Expand Down Expand Up @@ -3184,6 +3201,11 @@ pub const Type = struct {
/// `.none` means no sentinel, `.unknown_unknown` means unknown sentinel
sentinel: InternPool.Index,
is_const: bool,
is_volatile: bool = false,
is_allowzero: bool = false,
/// `0` means default alignment.
alignment: u16 = 0,
address_space: std.builtin.AddressSpace = .generic,
Comment on lines +3204 to +3208
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a type that can store most pointer attributes.

elem_ty: *Type,
/// `.none` means no sentinel, `.unknown_unknown` means unknown sentinel
sentinel: InternPool.Index,
flags: InternPool.Key.Pointer.Flags,

elem_ty: *Type,
},

Expand Down Expand Up @@ -3290,6 +3312,10 @@ pub const Type = struct {
size: std.builtin.Type.Pointer.Size,
sentinel: InternPool.Index,
is_const: bool,
is_volatile: bool,
is_allowzero: bool,
alignment: u16,
address_space: std.builtin.AddressSpace,
elem_ty: Type,
Comment on lines 3312 to 3319
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a type that can store most pointer attributes. So the number of function parameters can be reduced here:

Suggested change
size: std.builtin.Type.Pointer.Size,
sentinel: InternPool.Index,
is_const: bool,
is_volatile: bool,
is_allowzero: bool,
alignment: u16,
address_space: std.builtin.AddressSpace,
elem_ty: Type,
elem_ty: Type,
sentinel: InternPool.Index,
flags: InternPool.Key.Pointer.Flags,

) !Data {
std.debug.assert(elem_ty.is_type_val);
Expand All @@ -3302,6 +3328,10 @@ pub const Type = struct {
.flags = .{
.size = size,
.is_const = is_const,
.is_volatile = is_volatile,
.is_allowzero = is_allowzero,
.alignment = alignment,
.address_space = address_space,
},
},
});
Expand All @@ -3312,6 +3342,10 @@ pub const Type = struct {
.size = size,
.sentinel = sentinel,
.is_const = is_const,
.is_volatile = is_volatile,
.is_allowzero = is_allowzero,
.alignment = alignment,
.address_space = address_space,
.elem_ty = try analyser.allocType(elem_ty),
},
};
Expand Down Expand Up @@ -3666,11 +3700,18 @@ pub const Type = struct {
return t.data.resolveGeneric(analyser, bound_params, visiting);
},
.pointer => |info| {
const size = info.size;
const sentinel = info.sentinel;
const is_const = info.is_const;
const elem_ty = try analyser.resolveGenericTypeInternal(info.elem_ty.*, bound_params, visiting);
return try createPointer(analyser, size, sentinel, is_const, elem_ty);
return try createPointer(
analyser,
info.size,
info.sentinel,
info.is_const,
info.is_volatile,
info.is_allowzero,
info.alignment,
info.address_space,
elem_ty,
);
},
.array => |info| {
const elem_count = info.elem_count;
Expand Down Expand Up @@ -3769,10 +3810,24 @@ pub const Type = struct {
size: std.builtin.Type.Pointer.Size,
sentinel: InternPool.Index,
is_const: bool,
is_volatile: bool,
is_allowzero: bool,
alignment: u16,
address_space: std.builtin.AddressSpace,
elem_ty: Type,
Comment on lines 3810 to 3817
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a type that can store most pointer attributes. So the number of function parameters can be reduced here:

Suggested change
size: std.builtin.Type.Pointer.Size,
sentinel: InternPool.Index,
is_const: bool,
is_volatile: bool,
is_allowzero: bool,
alignment: u16,
address_space: std.builtin.AddressSpace,
elem_ty: Type,
elem_ty: Type,
sentinel: InternPool.Index,
flags: InternPool.Key.Pointer.Flags,

) !Type {
return .{
.data = try Data.createPointer(analyser, size, sentinel, is_const, elem_ty),
.data = try Data.createPointer(
analyser,
size,
sentinel,
is_const,
is_volatile,
is_allowzero,
alignment,
address_space,
elem_ty,
),
.is_type_val = true,
};
}
Expand Down Expand Up @@ -4605,7 +4660,11 @@ pub const Type = struct {
},
.c => try writer.writeAll("[*c]"),
}
if (info.is_allowzero and info.size != .c) try writer.writeAll("allowzero ");
if (info.alignment != 0) try writer.print("align({d}) ", .{info.alignment});
if (info.address_space != .generic) try writer.print("addrspace(.{t}) ", .{info.address_space});
if (info.is_const) try writer.writeAll("const ");
if (info.is_volatile) try writer.writeAll("volatile ");
try info.elem_ty.rawStringify(writer, analyser, options);
},
.array => |info| {
Expand Down Expand Up @@ -4878,7 +4937,7 @@ fn resolveLangrefType(analyser: *Analyser, type_str: []const u8) Error!?Type {
elem_str = elem_str[6..];
const elem_instance = try analyser.resolveLangrefType(elem_str) orelse return null;
const elem_ty = try elem_instance.typeOf(analyser);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, is_const, elem_ty);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, is_const, false, false, 0, .generic, elem_ty);
return try pointer_ty.instanceUnchecked(analyser);
}

Expand Down Expand Up @@ -4914,7 +4973,7 @@ fn resolveLangrefType(analyser: *Analyser, type_str: []const u8) Error!?Type {
elem_str = elem_str[6..];
const elem_instance = try analyser.resolveLangrefType(elem_str) orelse return null;
const elem_ty = try elem_instance.typeOf(analyser);
const slice_ty = try Type.createPointerType(analyser, .slice, sentinel, is_const, elem_ty);
const slice_ty = try Type.createPointerType(analyser, .slice, sentinel, is_const, false, false, 0, .generic, elem_ty);
return try slice_ty.instanceUnchecked(analyser);
}

Expand Down Expand Up @@ -6018,7 +6077,7 @@ pub const DeclWithHandle = struct {
if (!self.isCaptureByRef()) return resolved_ty;

const elem_ty = try resolved_ty.typeOf(analyser);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, false, elem_ty);
const pointer_ty = try Type.createPointerType(analyser, .one, .none, false, false, false, 0, .generic, elem_ty);
return try pointer_ty.instanceUnchecked(analyser);
}
};
Expand Down
27 changes: 27 additions & 0 deletions tests/lsp_features/inlay_hints.zig
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,33 @@ test "var decl" {
, .{ .kind = .Type });
}

test "var decl - pointer modifiers" {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests shouldn't need to go through inlay hints. Instead, add new tests to tests/analysis/pointer.zig which directly target the analysis backend without going through LSP requests.

Example:

diff --git a/tests/analysis/pointer.zig b/tests/analysis/pointer.zig
index 4086f8d4..5aa7acab 100644
--- a/tests/analysis/pointer.zig
+++ b/tests/analysis/pointer.zig
@@ -270,6 +270,9 @@ const ManyPointerWithSentinel = [*:.{}]addrspace(.generic) const packed struct {
 //                                 ^ (packed struct {})()
 //                                               ^^^^^^^^ (AddressSpace)()
 
+const VolatilePointer = *volatile u32;
+//    ^^^^^^^^^^^^^^^ (type)(*volatile u32)
+
 var runtime_index: usize = 5;
 var runtime_u8: u8 = 1;
 var runtime_i8: i8 = -1;

try testInlayHints(
\\const a: *u8 = undefined;
\\const b<*u8> = a;
, .{ .kind = .Type });
try testInlayHints(
\\const a: *allowzero u8 = undefined;
\\const b<*allowzero u8> = a;
, .{ .kind = .Type });
try testInlayHints(
\\const a: *align(4) u8 = undefined;
\\const b<*align(4) u8> = a;
, .{ .kind = .Type });
try testInlayHints(
\\const a: *volatile u8 = undefined;
\\const b<*volatile u8> = a;
, .{ .kind = .Type });
try testInlayHints(
\\const a: *allowzero align(8) const volatile u8 = undefined;
\\const b<*allowzero align(8) const volatile u8> = a;
, .{ .kind = .Type });
try testInlayHints(
\\const a: [*]allowzero u8 = undefined;
\\const b<[*]allowzero u8> = a;
, .{ .kind = .Type });
}

test "comptime return types" {
try testInlayHints(
\\fn Box(comptime T: type) type {
Expand Down
Loading