Completes comptime-cursor tuple indexing (started by the read path infee86adf) and unblocks the `race` runtime synthesis. Five enablers: 1. Named-tuple-literal type inference preserves element NAMES. A `.(a = x, b = y)` passed DIRECTLY as a `$T` argument inferred to a tuple with `.names = null`, so `field_name(T, i)` reflected "" and a `make_enum` over those labels collided on the empty name. The typer now mirrors `lowerTupleLiteral`'s name capture. 2. `inferExprType` resolves a comptime-constant tuple index to the i-th field's CONCRETE type (the inference sibling of thefee86adfread path), so `tup[i].field` / methods / comparisons on it resolve. 3. Tuple-element L-VALUES by comptime index — `tup[i] = v`, `tup[i].f = v`, `@tup[i]` — lower to a typed `structGep` of field i across all four paths (`lowerAssignment`, the multi-assign store, `lowerExprAsPtr`, and address-of-index). Previously each emitted an `index_gep` with a `ptrTo(.unresolved)` element type (a tuple has no uniform element) that panicked at LLVM emit. An out-of-range comptime index now diagnoses loudly on every path instead of falling through to that panic. 4. A user generic `($X..) -> Type` call is recognized as type-shaped (`isTypeReturningCallNode`), so it can bind a `$E: Type` parameter — e.g. `make_variant(RaceResult(T), i, …)`. The static `isTypeShapedAstNode` only knew the type-returning builtins (field_type/pointee/type_of). Locked by examples/comptime/0652 (read,fee86adf) and 0653 (store + address-of + element-pointer field store).
36 lines
1.5 KiB
Plaintext
36 lines
1.5 KiB
Plaintext
// Comptime-cursor tuple-element L-VALUES: writing a named-tuple element by a
|
|
// comptime-constant index — the store/address-of siblings of 0652's read path.
|
|
// A tuple is heterogeneous, so each element L-value is a typed `structGep` of the
|
|
// i-th field (not a uniform `index_gep`): `tup[i] = v` (direct store), a field
|
|
// store through an element pointer (`tup[i].f = v`), and `@tup[i]` (address-of).
|
|
// These are what the `race` runtime needs to register a waiter on the i-th task
|
|
// handle (`tasks[i].waiter = …`). An out-of-range comptime index is a loud
|
|
// compile error on every one of these paths (no silent `ptrTo(unresolved)` panic).
|
|
#import "modules/std.sx";
|
|
|
|
Box :: struct ($R: Type) { value: R; }
|
|
|
|
main :: () -> i32 {
|
|
// Direct element store by literal index.
|
|
t := .(a = 1, b = 2, c = 3);
|
|
t[0] = 100;
|
|
t[2] = 300;
|
|
print("t = ({}, {}, {})\n", t.a, t.b, t.c);
|
|
|
|
// Address-of an element, write through the pointer.
|
|
p := @t[1];
|
|
p.* = 200;
|
|
print("t.b via @t[1] = {}\n", t.b);
|
|
|
|
// Field store THROUGH an element pointer — `tup[i].field = v` — the exact
|
|
// L-value shape `race` uses to register a waiter (`tasks[i].waiter = …`): the
|
|
// i-th element is a `*Box`, and `.value` writes through it to the pointee.
|
|
ba : Box(i64) = .{ value = 0 };
|
|
bb : Box(bool) = .{ value = false };
|
|
handles := .(x = @ba, y = @bb);
|
|
handles[0].value = 7;
|
|
handles[1].value = true;
|
|
print("ba.value = {}, bb.value = {}\n", ba.value, bb.value);
|
|
return 0;
|
|
}
|