fix: slicing a many-pointer yields a correct slice (issue 0159)

emitSubslice handled a struct (slice/string) base and an array base, but a
many-pointer [*]T base is an LLVM pointer kind — it fell through to the else arm
that mapped the result to LLVMGetUndef(slice_ty), so a slice of a many-pointer
(mp[lo..hi]) had a garbage .len/.ptr and iterating it segfaulted.

Add a LLVMPointerTypeKind branch: the base value IS the data pointer, so GEP by
lo and len = hi - lo (the caller supplies the bound; no length is read from the
unbounded pointer). An open-ended mp[lo..] has no resolvable upper bound (a [*]T
carries no length), so lowerSliceExpr now diagnoses it instead of emitting a
.length op that yields garbage.

A List (whose items is [*]T) is now iterable with for items[0..len] (e);
applied in Scheduler.deinit. Regressions: examples/types/0195 (valid slice +
List for-each) + examples/diagnostics/1192 (open-ended rejection).
This commit is contained in:
agra
2026-06-22 10:15:18 +03:00
parent 55ed9a248e
commit b9311e7de4
12 changed files with 148 additions and 5 deletions

View File

@@ -1483,7 +1483,14 @@ pub fn lowerSliceExpr(self: *Lowering, se: *const ast.SliceExpr) Ref {
self.lowerExpr(e)
else if (!obj_ty.isBuiltin() and self.module.types.get(obj_ty) == .array)
self.builder.constInt(@intCast(self.module.types.get(obj_ty).array.length), .i64)
else
else if (!obj_ty.isBuiltin() and self.module.types.get(obj_ty) == .many_pointer) blk: {
// A many-pointer `[*]T` carries no length, so an open-ended slice
// `mp[lo..]` has no upper bound to resolve — a `.length` op on it would
// yield a garbage length (issue 0159). Require an explicit `hi`.
if (self.diagnostics) |d|
d.addFmt(.err, se.object.span, "slicing a many-pointer `[*]T` requires an explicit upper bound (`mp[lo..hi]`) — it has no length", .{});
break :blk self.builder.constInt(0, .i64);
} else
self.builder.emit(.{ .length = .{ .operand = obj } }, .i64);
if (se.end_inclusive) hi = self.builder.add(hi, self.builder.constInt(1, .i64), .i64);
// Subslice of string stays string (same {ptr, i64} layout, correct type category)