Skip to content

Commit 22fc237

Browse files
FnControlOptionTechatrix
authored andcommitted
Fix resolved type of slice with sentinel
1 parent 9fb711a commit 22fc237

3 files changed

Lines changed: 67 additions & 36 deletions

File tree

src/analysis.zig

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,21 +1092,32 @@ pub fn resolveDerefBinding(analyser: *Analyser, pointer: Type) error{OutOfMemory
10921092
pub const BracketAccess = union(enum) {
10931093
/// `lhs[index]`
10941094
single: ?u64,
1095-
/// `lhs[start..]`
1096-
open: ?u64,
1097-
/// `lhs[start..end]`
1098-
range: ?struct { u64, u64 },
1095+
/// `lhs[start.. :sentinel]`
1096+
open: struct {
1097+
start: ?u64,
1098+
sentinel: ?InternPool.Index,
1099+
},
1100+
/// `lhs[start..end :sentinel]`
1101+
range: struct {
1102+
bounds: ?struct { u64, u64 },
1103+
sentinel: ?InternPool.Index,
1104+
},
10991105

11001106
pub fn fromSlice(
11011107
analyser: *Analyser,
11021108
handle: *DocumentStore.Handle,
1103-
start_node: Ast.Node.Index,
1104-
end_node_maybe: ?Ast.Node.Index,
1109+
slice: Ast.full.Slice,
11051110
) error{OutOfMemory}!BracketAccess {
1106-
const end_node = end_node_maybe orelse
1107-
return .{ .open = try analyser.resolveIntegerLiteral(u64, .of(start_node, handle)) };
1111+
const start_node = slice.ast.start;
1112+
const end_node = slice.ast.end.unwrap() orelse
1113+
return .{
1114+
.open = .{
1115+
.start = try analyser.resolveIntegerLiteral(u64, .of(start_node, handle)),
1116+
.sentinel = try analyser.resolveOptionalIPValue(slice.ast.sentinel, handle),
1117+
},
1118+
};
11081119

1109-
const range = blk: {
1120+
const bounds = blk: {
11101121
const start = try analyser.resolveIntegerLiteral(u64, .of(start_node, handle)) orelse
11111122
break :blk null;
11121123

@@ -1116,7 +1127,12 @@ pub const BracketAccess = union(enum) {
11161127
break :blk .{ start, end };
11171128
};
11181129

1119-
return .{ .range = range };
1130+
return .{
1131+
.range = .{
1132+
.bounds = bounds,
1133+
.sentinel = try analyser.resolveOptionalIPValue(slice.ast.sentinel, handle),
1134+
},
1135+
};
11201136
}
11211137
};
11221138

@@ -1185,8 +1201,8 @@ pub fn resolveBracketAccessTypeFromBinding(analyser: *Analyser, lhs_binding: Bin
11851201
},
11861202
.array => |info| switch (rhs) {
11871203
.single => return try info.elem_ty.instanceTypeVal(analyser),
1188-
.open => |start_maybe| {
1189-
if (start_maybe) |start| {
1204+
.open => |access| {
1205+
if (access.start) |start| {
11901206
result = .{ .array = null };
11911207
if (info.elem_count) |elem_count| {
11921208
if (start <= elem_count) {
@@ -1197,16 +1213,17 @@ pub fn resolveBracketAccessTypeFromBinding(analyser: *Analyser, lhs_binding: Bin
11971213
sentinel = info.sentinel;
11981214
break :elem info.elem_ty;
11991215
},
1200-
.range => |range_maybe| {
1201-
if (range_maybe) |range| {
1216+
.range => |access| {
1217+
if (access.bounds) |bounds| {
12021218
result = .{ .array = null };
12031219
if (info.elem_count) |elem_count| {
1204-
const start, const end = range;
1220+
const start, const end = bounds;
12051221
if (start <= end and start <= elem_count and end <= elem_count) {
12061222
result = .{ .array = end - start };
12071223
}
12081224
}
12091225
}
1226+
sentinel = access.sentinel orelse .none;
12101227
break :elem info.elem_ty;
12111228
},
12121229
},
@@ -1215,8 +1232,9 @@ pub fn resolveBracketAccessTypeFromBinding(analyser: *Analyser, lhs_binding: Bin
12151232
.tuple, .array => continue :elem info.elem_ty.data,
12161233
else => switch (rhs) {
12171234
.single, .open => return null,
1218-
.range => |range_maybe| {
1219-
const start, const end = range_maybe orelse return null;
1235+
.range => |access| {
1236+
if (access.sentinel != null) return null;
1237+
const start, const end = access.bounds orelse return null;
12201238
if (start > end or start > 1 or end > 1) return null;
12211239
result = .{ .array = end - start };
12221240
break :elem info.elem_ty;
@@ -1226,11 +1244,12 @@ pub fn resolveBracketAccessTypeFromBinding(analyser: *Analyser, lhs_binding: Bin
12261244
.many, .slice, .c => switch (rhs) {
12271245
.single => try info.elem_ty.instanceTypeVal(analyser),
12281246
.open => lhs,
1229-
.range => |range_maybe| {
1230-
if (range_maybe) |range| {
1231-
const start, const end = range;
1247+
.range => |access| {
1248+
if (access.bounds) |bounds| {
1249+
const start, const end = bounds;
12321250
result = .{ .array = if (start <= end) end - start else null };
12331251
}
1252+
sentinel = access.sentinel orelse .none;
12341253
break :elem info.elem_ty;
12351254
},
12361255
},
@@ -1359,6 +1378,15 @@ fn allDigits(str: []const u8) bool {
13591378
return true;
13601379
}
13611380

1381+
fn resolveOptionalIPValue(
1382+
analyser: *Analyser,
1383+
optional_node: Ast.Node.OptionalIndex,
1384+
handle: *DocumentStore.Handle,
1385+
) error{OutOfMemory}!?InternPool.Index {
1386+
const node = optional_node.unwrap() orelse return null;
1387+
return try analyser.resolveInternPoolValue(.of(node, handle));
1388+
}
1389+
13621390
fn resolveInternPoolValue(analyser: *Analyser, options: ResolveOptions) error{OutOfMemory}!?InternPool.Index {
13631391
const old_resolve_number_literal_values = analyser.resolve_number_literal_values;
13641392
analyser.resolve_number_literal_values = true;
@@ -1978,10 +2006,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
19782006
=> {
19792007
const ptr_info = ast.fullPtrType(tree, node).?;
19802008

1981-
const sentinel = if (ptr_info.ast.sentinel.unwrap()) |sentinel|
1982-
try analyser.resolveInternPoolValue(.of(sentinel, handle)) orelse .none
1983-
else
1984-
.none;
2009+
const sentinel = try analyser.resolveOptionalIPValue(ptr_info.ast.sentinel, handle) orelse .none;
19852010

19862011
const elem_ty = try analyser.resolveTypeOfNodeInternal(.of(ptr_info.ast.child_type, handle)) orelse return null;
19872012
if (!elem_ty.is_type_val) return null;
@@ -2004,10 +2029,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
20042029
const array_info = tree.fullArrayType(node).?;
20052030

20062031
const elem_count = try analyser.resolveIntegerLiteral(u64, .of(array_info.ast.elem_count, handle));
2007-
const sentinel = if (array_info.ast.sentinel.unwrap()) |sentinel|
2008-
try analyser.resolveInternPoolValue(.of(sentinel, handle)) orelse .none
2009-
else
2010-
.none;
2032+
const sentinel = try analyser.resolveOptionalIPValue(array_info.ast.sentinel, handle) orelse .none;
20112033

20122034
const elem_ty = try analyser.resolveTypeOfNodeInternal(.of(array_info.ast.elem_type, handle)) orelse return null;
20132035
if (!elem_ty.is_type_val) return null;
@@ -2966,7 +2988,7 @@ fn resolveBindingOfNodeUncached(analyser: *Analyser, options: ResolveOptions) er
29662988

29672989
const sliced = try analyser.resolveBindingOfNodeInternal(.of(slice.ast.sliced, handle)) orelse return null;
29682990

2969-
const kind: BracketAccess = try .fromSlice(analyser, handle, slice.ast.start, slice.ast.end.unwrap());
2991+
const kind: BracketAccess = try .fromSlice(analyser, handle, slice);
29702992

29712993
return .{
29722994
.type = try analyser.resolveBracketAccessTypeFromBinding(sliced, kind) orelse return null,
@@ -4617,12 +4639,12 @@ pub fn getFieldAccessType(
46174639
},
46184640
.ellipsis2 => {
46194641
if (bracket_count == 1) {
4620-
kind = .{ .open = null };
4642+
kind = .{ .open = .{ .start = null, .sentinel = .none } };
46214643
}
46224644
},
46234645
else => {
46244646
if (bracket_count == 1 and kind == .open) {
4625-
kind = .{ .range = null };
4647+
kind = .{ .range = .{ .bounds = null, .sentinel = .none } };
46264648
}
46274649
},
46284650
}

tests/analysis/array.zig

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ const array_slice_open_runtime = some_array[runtime_index..];
5353
const array_slice_0_2 = some_array[0..2];
5454
// ^^^^^^^^^^^^^^^ (*const [2]u8)()
5555

56-
// TODO this should be `*const [2 :0]u8`
5756
const array_slice_0_2_sentinel = some_array[0..2 :0];
58-
// ^^^^^^^^^^^^^^^^^^^^^^^^ (*const [2]u8)()
57+
// ^^^^^^^^^^^^^^^^^^^^^^^^ (*const [2:0]u8)()
5958

6059
const array_slice_0_5 = some_array[0..5];
6160
// ^^^^^^^^^^^^^^^ (*const [?]u8)()
@@ -66,9 +65,8 @@ const array_slice_3_2 = some_array[3..2];
6665
const array_slice_0_runtime = some_array[0..runtime_index];
6766
// ^^^^^^^^^^^^^^^^^^^^^ ([]const u8)()
6867

69-
// TODO this should be `[:0]const u8`
7068
const array_slice_with_sentinel = some_array[0..runtime_index :0];
71-
// ^^^^^^^^^^^^^^^^^^^^^^^^^ ([]const u8)()
69+
// ^^^^^^^^^^^^^^^^^^^^^^^^^ ([:0]const u8)()
7270

7371
//
7472
// Array init

tests/analysis/pointer.zig

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ const one_u32_slice_len_1_1 = one_u32[1..1];
3232
const one_u32_slice_open = one_u32[1..];
3333
// ^^^^^^^^^^^^^^^^^^ (unknown)()
3434

35+
const one_u32_slice_sentinel = one_u32[0..1 :2];
36+
// ^^^^^^^^^^^^^^^^^^^^^^ (unknown)()
37+
3538
const one_u32_orelse = one_u32 orelse unreachable;
3639
// ^^^^^^^^^^^^^^ (unknown)()
3740

@@ -84,6 +87,9 @@ const many_u32_slice_len_runtime = many_u32[0..runtime_index];
8487
const many_u32_slice_open = many_u32[1..];
8588
// ^^^^^^^^^^^^^^^^^^^ ([*]const u32)()
8689

90+
const many_u32_slice_sentinel = many_u32[0..1 :2];
91+
// ^^^^^^^^^^^^^^^^^^^^^^^ (*const [1:2]u32)()
92+
8793
const many_u32_orelse = many_u32 orelse unreachable;
8894
// ^^^^^^^^^^^^^^^ (unknown)()
8995

@@ -135,10 +141,12 @@ const slice_u32_slice_len_comptime = slice_u32[0..2];
135141
const slice_u32_slice_len_runtime = slice_u32[0..runtime_index];
136142
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ([]const u32)()
137143

138-
// TODO this should be `*const [1]u32`
139144
const slice_u32_slice_open = slice_u32[1..];
140145
// ^^^^^^^^^^^^^^^^^^^^ ([]const u32)()
141146

147+
const slice_u32_slice_sentinel = slice_u32[0..1 :2];
148+
// ^^^^^^^^^^^^^^^^^^^^^^^^ (*const [1:2]u32)()
149+
142150
const slice_u32_orelse = slice_u32 orelse unreachable;
143151
// ^^^^^^^^^^^^^^^^ (unknown)()
144152

@@ -191,6 +199,9 @@ const c_u32_slice_len_runtime = c_u32[0..runtime_index];
191199
const c_u32_slice_open = c_u32[1..];
192200
// ^^^^^^^^^^^^^^^^ ([*c]const u32)()
193201

202+
const c_u32_slice_sentinel = c_u32[0..1 :2];
203+
// ^^^^^^^^^^^^^^^^^^^^ (*const [1:2]u32)()
204+
194205
const c_u32_orelse = c_u32 orelse unreachable;
195206
// ^^^^^^^^^^^^ ([*c]const u32)()
196207

0 commit comments

Comments
 (0)