ffi: drop legacy name: ..T variadic syntax

Parser hard-rejects the legacy `name: ..T` form with a one-line
migration message pointing at the new `..name: []T` shape. The
leading-`..` form is the one the lowering paths
(`resolveParamType` / `packVariadicCallArgs`) treat as canonical
post-issue-0049; leaving both forms accepted invited the same
class of cross-module emit crashes any time a `..T`-form decl in
stdlib crossed an import boundary.

`specs.md` updated alongside: the Variadic Functions section now
documents `..name: []T` as the surface form, with notes on
homogeneous vs `[]Any` boxing and the `..` spread at call sites.
Inline references to `args: ..Any` in §7 and §8 refreshed.
This commit is contained in:
agra
2026-05-27 21:32:45 +03:00
parent 5b3d86440b
commit 952dc0e161
2 changed files with 24 additions and 13 deletions

View File

@@ -1631,12 +1631,15 @@ pub const Parser = struct {
continue;
}
self.advance(); // consume ':'
// Old syntax keeps the variadic marker after the colon
// (`args: ..T`). Accept it even if a leading `..` already
// appeared — both forms set the same flag.
// The legacy `name: ..T` form is rejected — write `..name: []T`.
// Both forms used to live; the leading-`..` form is the one the
// language settled on (the AST shape downstream assumes the
// declared type IS the slice). Leaving the post-colon form
// accepted lets users land code that bypasses the new-form
// lowering paths (resolveParamType / packVariadicCallArgs) and
// hit cross-module emit crashes (issue-0049). Hard error here.
if (self.current.tag == .dot_dot) {
is_variadic = true;
self.advance();
return self.fail("legacy variadic syntax `name: ..T` is no longer supported — use `..name: []T` instead");
}
const param_type = try self.parseTypeExpr();
var is_comptime_param = false;