lang: rename signed integer types sN -> iN
Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.
Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).
Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.
zig build test: 426/426; examples suite: 595/595.
This commit is contained in:
@@ -18,13 +18,13 @@ test "lower: simple function with arithmetic" {
|
||||
var module = ir_mod.Module.init(alloc);
|
||||
defer module.deinit();
|
||||
|
||||
// Build a minimal AST: add :: (a: s64, b: s64) -> s64 { return a + b; }
|
||||
// Build a minimal AST: add :: (a: i64, b: i64) -> i64 { return a + b; }
|
||||
const a_type = alloc.create(Node) catch unreachable;
|
||||
a_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
a_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
const b_type = alloc.create(Node) catch unreachable;
|
||||
b_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
b_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
const ret_type = alloc.create(Node) catch unreachable;
|
||||
ret_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
ret_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
|
||||
const a_ident = alloc.create(Node) catch unreachable;
|
||||
a_ident.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .identifier = .{ .name = "a" } } };
|
||||
@@ -73,7 +73,7 @@ test "lower: simple function with arithmetic" {
|
||||
try std.testing.expectEqual(@as(usize, 1), module.functions.items.len);
|
||||
const func = module.getFunction(FuncId.fromIndex(0));
|
||||
try std.testing.expectEqual(@as(usize, 2), func.params.len);
|
||||
try std.testing.expectEqual(TypeId.s64, func.ret);
|
||||
try std.testing.expectEqual(TypeId.i64, func.ret);
|
||||
try std.testing.expect(func.blocks.items.len > 0);
|
||||
|
||||
// Print the IR to verify it looks reasonable
|
||||
@@ -94,15 +94,15 @@ test "lower: instructions carry their AST node's source span (ERR E3.0)" {
|
||||
var module = ir_mod.Module.init(alloc);
|
||||
defer module.deinit();
|
||||
|
||||
// probe :: (a: s64, b: s64) -> s64 { return a + b; } — the `a + b` node
|
||||
// probe :: (a: i64, b: i64) -> i64 { return a + b; } — the `a + b` node
|
||||
// gets a distinctive span so we can find the emitted `add` instruction and
|
||||
// assert it was stamped (not left at the empty {0,0} default).
|
||||
const a_type = alloc.create(Node) catch unreachable;
|
||||
a_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
a_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
const b_type = alloc.create(Node) catch unreachable;
|
||||
b_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
b_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
const ret_type = alloc.create(Node) catch unreachable;
|
||||
ret_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
ret_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
const a_ident = alloc.create(Node) catch unreachable;
|
||||
a_ident.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .identifier = .{ .name = "a" } } };
|
||||
const b_ident = alloc.create(Node) catch unreachable;
|
||||
@@ -154,7 +154,7 @@ test "lower: if/else generates basic blocks" {
|
||||
var module = ir_mod.Module.init(alloc);
|
||||
defer module.deinit();
|
||||
|
||||
// Build AST: test :: (c: bool) -> s64 { if c { return 1; } else { return 2; } }
|
||||
// Build AST: test :: (c: bool) -> i64 { if c { return 1; } else { return 2; } }
|
||||
// The condition must be a runtime value (a param) — a constant `if true`
|
||||
// is folded by lowering to a single block, defeating the branch test.
|
||||
const cond_node = alloc.create(Node) catch unreachable;
|
||||
@@ -204,7 +204,7 @@ test "lower: if/else generates basic blocks" {
|
||||
|
||||
const ret_type = alloc.create(Node) catch unreachable;
|
||||
defer alloc.destroy(ret_type);
|
||||
ret_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
ret_type.* = .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
|
||||
const fn_decl = ast.FnDecl{
|
||||
.name = "test_if",
|
||||
@@ -303,18 +303,18 @@ test "lower: objcTypeEncodingFromSignature emits primitive shapes" {
|
||||
defer alloc.free(e1);
|
||||
try std.testing.expectEqualStrings("v@:", e1);
|
||||
|
||||
// Returns s32, takes s32: -(int)add:(int)x → "i@:i"
|
||||
const e2 = try lowering.objc().objcTypeEncodingFromSignature(.s32, &.{.s32}, null);
|
||||
// Returns i32, takes i32: -(int)add:(int)x → "i@:i"
|
||||
const e2 = try lowering.objc().objcTypeEncodingFromSignature(.i32, &.{.i32}, null);
|
||||
defer alloc.free(e2);
|
||||
try std.testing.expectEqualStrings("i@:i", e2);
|
||||
|
||||
// s64 return, two s64 args: "q@:qq"
|
||||
const e3 = try lowering.objc().objcTypeEncodingFromSignature(.s64, &.{ .s64, .s64 }, null);
|
||||
// i64 return, two i64 args: "q@:qq"
|
||||
const e3 = try lowering.objc().objcTypeEncodingFromSignature(.i64, &.{ .i64, .i64 }, null);
|
||||
defer alloc.free(e3);
|
||||
try std.testing.expectEqualStrings("q@:qq", e3);
|
||||
|
||||
// BOOL return (s8): "c@:"
|
||||
const e4 = try lowering.objc().objcTypeEncodingFromSignature(.s8, &.{}, null);
|
||||
// BOOL return (i8): "c@:"
|
||||
const e4 = try lowering.objc().objcTypeEncodingFromSignature(.i8, &.{}, null);
|
||||
defer alloc.free(e4);
|
||||
try std.testing.expectEqualStrings("c@:", e4);
|
||||
|
||||
@@ -357,9 +357,9 @@ test "lower: objcTypeEncodingFromSignature emits pointer shapes" {
|
||||
defer alloc.free(e2);
|
||||
try std.testing.expectEqualStrings("v@:*", e2);
|
||||
|
||||
// `[*]s32` (non-u8 many-pointer) → `^v`.
|
||||
const s32_many = module.types.intern(.{ .many_pointer = .{ .element = .s32 } });
|
||||
const e3 = try lowering.objc().objcTypeEncodingFromSignature(.void, &.{s32_many}, null);
|
||||
// `[*]i32` (non-u8 many-pointer) → `^v`.
|
||||
const i32_many = module.types.intern(.{ .many_pointer = .{ .element = .i32 } });
|
||||
const e3 = try lowering.objc().objcTypeEncodingFromSignature(.void, &.{i32_many}, null);
|
||||
defer alloc.free(e3);
|
||||
try std.testing.expectEqualStrings("v@:^v", e3);
|
||||
}
|
||||
@@ -371,14 +371,14 @@ test "lower: objcDefinedStateStructType collects user-declared fields" {
|
||||
defer module.deinit();
|
||||
var lowering = Lowering.init(&module);
|
||||
|
||||
// Synthesize a #objc_class("SxFoo") { counter: s32; ticks: s64; } AST.
|
||||
// Synthesize a #objc_class("SxFoo") { counter: i32; ticks: i64; } AST.
|
||||
const span = ast.Span{ .start = 0, .end = 0 };
|
||||
const counter_type = try alloc.create(Node);
|
||||
defer alloc.destroy(counter_type);
|
||||
counter_type.* = .{ .span = span, .data = .{ .type_expr = .{ .name = "s32", .is_generic = false } } };
|
||||
counter_type.* = .{ .span = span, .data = .{ .type_expr = .{ .name = "i32", .is_generic = false } } };
|
||||
const ticks_type = try alloc.create(Node);
|
||||
defer alloc.destroy(ticks_type);
|
||||
ticks_type.* = .{ .span = span, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
ticks_type.* = .{ .span = span, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
|
||||
const members = [_]ast.ForeignClassMember{
|
||||
.{ .field = .{ .name = "counter", .field_type = counter_type } },
|
||||
@@ -401,9 +401,9 @@ test "lower: objcDefinedStateStructType collects user-declared fields" {
|
||||
try std.testing.expectEqualStrings("__SxFooState", module.types.getString(s.name));
|
||||
try std.testing.expectEqual(@as(usize, 2), s.fields.len);
|
||||
try std.testing.expectEqualStrings("counter", module.types.getString(s.fields[0].name));
|
||||
try std.testing.expectEqual(TypeId.s32, s.fields[0].ty);
|
||||
try std.testing.expectEqual(TypeId.i32, s.fields[0].ty);
|
||||
try std.testing.expectEqualStrings("ticks", module.types.getString(s.fields[1].name));
|
||||
try std.testing.expectEqual(TypeId.s64, s.fields[1].ty);
|
||||
try std.testing.expectEqual(TypeId.i64, s.fields[1].ty);
|
||||
|
||||
// Idempotency: a second call returns the same TypeId (cache hit on name).
|
||||
const state_ty2 = lowering.objc().objcDefinedStateStructType(&fcd);
|
||||
@@ -441,7 +441,7 @@ test "lower: objcDefinedStateStructType skips non-field members" {
|
||||
const span = ast.Span{ .start = 0, .end = 0 };
|
||||
const counter_type = try alloc.create(Node);
|
||||
defer alloc.destroy(counter_type);
|
||||
counter_type.* = .{ .span = span, .data = .{ .type_expr = .{ .name = "s32", .is_generic = false } } };
|
||||
counter_type.* = .{ .span = span, .data = .{ .type_expr = .{ .name = "i32", .is_generic = false } } };
|
||||
|
||||
const members = [_]ast.ForeignClassMember{
|
||||
.{ .extends = "NSObject" },
|
||||
@@ -519,10 +519,10 @@ test "lower: objcTypeEncodingFromSignature unwraps optional to wire type" {
|
||||
};
|
||||
try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd);
|
||||
|
||||
// `?s64 -> ?*NSString` collapses to `q -> @` at the Obj-C boundary.
|
||||
const opt_s64 = module.types.optionalOf(.s64);
|
||||
// `?i64 -> ?*NSString` collapses to `q -> @` at the Obj-C boundary.
|
||||
const opt_i64 = module.types.optionalOf(.i64);
|
||||
const opt_ns = module.types.optionalOf(ns_ptr);
|
||||
const e1 = try lowering.objc().objcTypeEncodingFromSignature(opt_ns, &.{opt_s64}, null);
|
||||
const e1 = try lowering.objc().objcTypeEncodingFromSignature(opt_ns, &.{opt_i64}, null);
|
||||
defer alloc.free(e1);
|
||||
try std.testing.expectEqualStrings("@@:q", e1);
|
||||
|
||||
@@ -571,7 +571,7 @@ test "lower: objcTypeEncodingFromSignature emits structs as {Name=fields...}" {
|
||||
.{ .name = len_name, .ty = .u64 },
|
||||
};
|
||||
const nsrange = module.types.intern(.{ .@"struct" = .{ .name = nsrange_name, .fields = &nsrange_fields } });
|
||||
const e3 = try lowering.objc().objcTypeEncodingFromSignature(nsrange, &.{ nsrange, .s64 }, null);
|
||||
const e3 = try lowering.objc().objcTypeEncodingFromSignature(nsrange, &.{ nsrange, .i64 }, null);
|
||||
defer alloc.free(e3);
|
||||
try std.testing.expectEqualStrings("{_NSRange=QQ}@:{_NSRange=QQ}q", e3);
|
||||
}
|
||||
@@ -712,7 +712,7 @@ test "lower: isObjcClassPointer recognises pointer-to-foreign-Obj-C-class" {
|
||||
|
||||
// *void and a builtin scalar → false (not object pointers).
|
||||
try std.testing.expect(!lowering.objc().isObjcClassPointer(module.types.ptrTo(.void)));
|
||||
try std.testing.expect(!lowering.objc().isObjcClassPointer(.s32));
|
||||
try std.testing.expect(!lowering.objc().isObjcClassPointer(.i32));
|
||||
}
|
||||
|
||||
test "lower: objcPropertyKind defaults + explicit ARC modifiers" {
|
||||
@@ -737,7 +737,7 @@ test "lower: objcPropertyKind defaults + explicit ARC modifiers" {
|
||||
try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd);
|
||||
|
||||
// Primitive field, no modifiers → assign (the non-object default).
|
||||
const prim = ast.ForeignFieldDecl{ .name = "count", .field_type = typeKeyword(alloc, "s32"), .is_property = true };
|
||||
const prim = ast.ForeignFieldDecl{ .name = "count", .field_type = typeKeyword(alloc, "i32"), .is_property = true };
|
||||
defer alloc.destroy(prim.field_type);
|
||||
try std.testing.expect(lowering.objc().objcPropertyKind(prim) == .assign);
|
||||
|
||||
@@ -982,11 +982,11 @@ test "E1.4c noreturn typing: divergence shapes + if-else unification + block pro
|
||||
defer alloc.destroy(lit);
|
||||
const then_div = mk.node(alloc, .{ .if_expr = .{ .condition = lit, .then_branch = ret, .else_branch = lit, .is_inline = false } });
|
||||
defer alloc.destroy(then_div);
|
||||
try std.testing.expectEqual(TypeId.s64, lowering.inferExprType(then_div)); // then diverges → else (s64)
|
||||
try std.testing.expectEqual(TypeId.i64, lowering.inferExprType(then_div)); // then diverges → else (i64)
|
||||
|
||||
const else_div = mk.node(alloc, .{ .if_expr = .{ .condition = lit, .then_branch = lit, .else_branch = ret, .is_inline = false } });
|
||||
defer alloc.destroy(else_div);
|
||||
try std.testing.expectEqual(TypeId.s64, lowering.inferExprType(else_div)); // then is s64
|
||||
try std.testing.expectEqual(TypeId.i64, lowering.inferExprType(else_div)); // then is i64
|
||||
|
||||
const both_div = mk.node(alloc, .{ .if_expr = .{ .condition = lit, .then_branch = ret, .else_branch = brk, .is_inline = false } });
|
||||
defer alloc.destroy(both_div);
|
||||
@@ -1059,13 +1059,13 @@ test "conversions: optionalOfFlattened wraps once, flattening a nested optional"
|
||||
defer module.deinit();
|
||||
var l = Lowering.init(&module);
|
||||
|
||||
const opt_s64 = module.types.optionalOf(.s64);
|
||||
const opt_i64 = module.types.optionalOf(.i64);
|
||||
// Wrap a non-optional: T -> ?T.
|
||||
try std.testing.expectEqual(opt_s64, l.optionalOfFlattened(.s64));
|
||||
try std.testing.expectEqual(opt_i64, l.optionalOfFlattened(.i64));
|
||||
// Wrap an already-optional FLATTENS: ?T -> ?T (the coercion never builds ??T).
|
||||
try std.testing.expectEqual(opt_s64, l.optionalOfFlattened(opt_s64));
|
||||
try std.testing.expectEqual(opt_i64, l.optionalOfFlattened(opt_i64));
|
||||
// Contrast: the plain wrap does NOT flatten — ?T -> ??T (distinct type).
|
||||
try std.testing.expect(module.types.optionalOf(opt_s64) != opt_s64);
|
||||
try std.testing.expect(module.types.optionalOf(opt_i64) != opt_i64);
|
||||
}
|
||||
|
||||
|
||||
@@ -1100,9 +1100,9 @@ test "lower: assigning to a missing struct field emits field-not-found, no panic
|
||||
var diags = errors.DiagnosticList.init(alloc, "", "test.sx");
|
||||
defer diags.deinit();
|
||||
|
||||
// Register `Point :: struct { x: s64; }` so the struct literal resolves.
|
||||
// Register `Point :: struct { x: i64; }` so the struct literal resolves.
|
||||
const fields = [_]ir_mod.types.TypeInfo.StructInfo.Field{
|
||||
.{ .name = module.types.internString("x"), .ty = .s64 },
|
||||
.{ .name = module.types.internString("x"), .ty = .i64 },
|
||||
};
|
||||
_ = module.types.intern(.{ .@"struct" = .{ .name = module.types.internString("Point"), .fields = &fields } });
|
||||
|
||||
@@ -1145,9 +1145,9 @@ test "lower: multi-assign to a missing struct field emits field-not-found, no co
|
||||
var diags = errors.DiagnosticList.init(alloc, "", "test.sx");
|
||||
defer diags.deinit();
|
||||
|
||||
// Register `Point :: struct { x: s64; }` so the struct literal resolves.
|
||||
// Register `Point :: struct { x: i64; }` so the struct literal resolves.
|
||||
const fields = [_]ir_mod.types.TypeInfo.StructInfo.Field{
|
||||
.{ .name = module.types.internString("x"), .ty = .s64 },
|
||||
.{ .name = module.types.internString("x"), .ty = .i64 },
|
||||
};
|
||||
_ = module.types.intern(.{ .@"struct" = .{ .name = module.types.internString("Point"), .fields = &fields } });
|
||||
|
||||
@@ -1198,23 +1198,23 @@ test "lower: shared resolver types a pointer-typed field GEP as *field_ty, not f
|
||||
|
||||
const span = ast.Span{ .start = 0, .end = 0 };
|
||||
|
||||
// Register `S :: struct { p: *s64; }` — the field's own type is a pointer.
|
||||
const ptr_s64 = module.types.ptrTo(.s64);
|
||||
// Register `S :: struct { p: *i64; }` — the field's own type is a pointer.
|
||||
const ptr_i64 = module.types.ptrTo(.i64);
|
||||
const fields = [_]ir_mod.types.TypeInfo.StructInfo.Field{
|
||||
.{ .name = module.types.internString("p"), .ty = ptr_s64 },
|
||||
.{ .name = module.types.internString("p"), .ty = ptr_i64 },
|
||||
};
|
||||
_ = module.types.intern(.{ .@"struct" = .{ .name = module.types.internString("S"), .fields = &fields } });
|
||||
|
||||
// mutate :: (s: *S, q: *s64) { d := 0; s.p, d = q, 1; }
|
||||
// mutate :: (s: *S, q: *i64) { d := 0; s.p, d = q, 1; }
|
||||
// The multi-assign target routes `s.p` through the shared fieldLvaluePtr
|
||||
// resolver. Pre-fix that resolver typed the field GEP with the bare field
|
||||
// value type (`*s64`), so emitStore unwrapped one level to `s64` and
|
||||
// value type (`*i64`), so emitStore unwrapped one level to `i64` and
|
||||
// coerceArg's closure auto-promotion stored a 16-byte struct over the
|
||||
// 8-byte field, clobbering the neighbour. The resolver now types the GEP
|
||||
// `*(*s64)` so emitStore stops at the field's own pointer type.
|
||||
// `*(*i64)` so emitStore stops at the field's own pointer type.
|
||||
var s_pointee = Node{ .span = span, .data = .{ .type_expr = .{ .name = "S", .is_generic = false } } };
|
||||
var s_ty = Node{ .span = span, .data = .{ .pointer_type_expr = .{ .pointee_type = &s_pointee } } };
|
||||
var q_pointee = Node{ .span = span, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
var q_pointee = Node{ .span = span, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
var q_ty = Node{ .span = span, .data = .{ .pointer_type_expr = .{ .pointee_type = &q_pointee } } };
|
||||
|
||||
var d_init = Node{ .span = span, .data = .{ .int_literal = .{ .value = 0 } } };
|
||||
@@ -1240,8 +1240,8 @@ test "lower: shared resolver types a pointer-typed field GEP as *field_ty, not f
|
||||
var lowering = Lowering.init(&module);
|
||||
lowering.lowerFunction(&fd, "mutate", false);
|
||||
|
||||
// The field-store GEP must be typed `*(*s64)`: its pointee is the field's
|
||||
// own type (`*s64`), not the field's pointee (`s64`).
|
||||
// The field-store GEP must be typed `*(*i64)`: its pointee is the field's
|
||||
// own type (`*i64`), not the field's pointee (`i64`).
|
||||
const func = module.getFunction(FuncId.fromIndex(0));
|
||||
var found = false;
|
||||
for (func.blocks.items) |blk| {
|
||||
@@ -1249,7 +1249,7 @@ test "lower: shared resolver types a pointer-typed field GEP as *field_ty, not f
|
||||
if (inst.op == .struct_gep) {
|
||||
const info = module.types.get(inst.ty);
|
||||
try std.testing.expect(info == .pointer);
|
||||
try std.testing.expectEqual(ptr_s64, info.pointer.pointee);
|
||||
try std.testing.expectEqual(ptr_i64, info.pointer.pointee);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
@@ -1264,7 +1264,7 @@ test "lower: reflectionArgIsType accepts spelled types, rejects plain values (is
|
||||
var l = Lowering.init(&module);
|
||||
|
||||
const span = ast.Span{ .start = 0, .end = 0 };
|
||||
const ty_node = Node{ .span = span, .data = .{ .type_expr = .{ .name = "s64", .is_generic = false } } };
|
||||
const ty_node = Node{ .span = span, .data = .{ .type_expr = .{ .name = "i64", .is_generic = false } } };
|
||||
const int_node = Node{ .span = span, .data = .{ .int_literal = .{ .value = 6 } } };
|
||||
const float_node = Node{ .span = span, .data = .{ .float_literal = .{ .value = 1.5 } } };
|
||||
const bool_node = Node{ .span = span, .data = .{ .bool_literal = .{ .value = true } } };
|
||||
@@ -1320,12 +1320,12 @@ test "lower: shadowed same-name author gets its own FuncId + real body (fix-0102
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
|
||||
try tmp.dir.writeFile(io, .{ .sub_path = "a.sx", .data = "greet :: () -> s64 { 1 }\nuse_greet :: () -> s64 { greet() }\n" });
|
||||
try tmp.dir.writeFile(io, .{ .sub_path = "b.sx", .data = "greet :: () -> s64 { 2 }\n" });
|
||||
try tmp.dir.writeFile(io, .{ .sub_path = "a.sx", .data = "greet :: () -> i64 { 1 }\nuse_greet :: () -> i64 { greet() }\n" });
|
||||
try tmp.dir.writeFile(io, .{ .sub_path = "b.sx", .data = "greet :: () -> i64 { 2 }\n" });
|
||||
const main_src =
|
||||
\\#import "a.sx";
|
||||
\\#import "b.sx";
|
||||
\\main :: () -> s64 { use_greet() }
|
||||
\\main :: () -> i64 { use_greet() }
|
||||
\\
|
||||
;
|
||||
try tmp.dir.writeFile(io, .{ .sub_path = "main.sx", .data = main_src });
|
||||
@@ -1487,7 +1487,7 @@ test "lower: scan populates source-keyed caches per declaring source (E0)" {
|
||||
const main_src =
|
||||
\\na :: #import "a.sx";
|
||||
\\nb :: #import "b.sx";
|
||||
\\main :: () -> s32 { 0 }
|
||||
\\main :: () -> i32 { 0 }
|
||||
\\
|
||||
;
|
||||
try tmp.dir.writeFile(io, .{ .sub_path = "main.sx", .data = main_src });
|
||||
|
||||
Reference in New Issue
Block a user