feat(lang): reserved-name check covers :: const/fn/type decls + scope call rewrite to raw provenance [F0.6]

A bare reserved-type-name `::` declaration was silently accepted, and the
attempt-2 lowerCall rewrite then made a bare `s2 :: (…) {…}` function callable —
bypassing the backtick rule for handwritten sx. The reserved-name binding check
covered `:=` / typed-local / param / captures but NOT the `::` declaration form.

- ast: `ConstDecl`/`FnDecl` carry `is_raw` + `name_span` threaded from the parser
  (parseConstBinding / parseFnDecl, all call sites incl. struct/impl methods).
- semantic_diagnostics: reject a bare reserved spelling at EVERY declaration-name
  site — const, function (incl. struct/impl methods), struct/enum/union/error-set,
  protocol, foreign-class, ufcs alias, namespaced/library/c-import name. Backtick
  (`is_raw`) and the compiler's `#builtin` definition (`string :: []u8 #builtin`)
  are the only exemptions; a value whose node is itself a named decl defers to
  that node's own check.
- c_import: synthesized foreign fn_decls are `is_raw = true`, so a C function
  whose own name collides with a reserved spelling (`int s2(int);`) imports and
  bare-calls unedited.
- lower: scope the `.type_expr`→`.identifier` call rewrite to a callee FnDecl of
  RAW provenance (`is_raw`) — only a backtick / `#import c` foreign fn can carry a
  reserved-name spelling, so a non-raw match never gets rewritten.
- examples: 0153 (positive — backtick `::` const + fn, bare + tick call), 1140
  (negative — bare `::` const + fn rejected).
- docs: specs.md + readme.md state the backtick is required at every binding site
  including `::` const / function / type declarations; issue 0089 banner updated.
This commit is contained in:
agra
2026-06-04 19:16:37 +03:00
parent 640f59dc54
commit c0e1a5db82
16 changed files with 232 additions and 62 deletions

View File

@@ -131,6 +131,14 @@ pub const FnDecl = struct {
type_params: []const StructTypeParam = &.{},
is_arrow: bool = false,
call_conv: CallingConvention = .default,
/// Span of the function's name token, for the reserved-type-name decl
/// diagnostic (issue 0089). Synthesized decls (e.g. `#import c` foreign
/// functions) leave it zero.
name_span: Span = .{ .start = 0, .end = 0 },
/// True when the function NAME was written as a backtick raw identifier
/// (`` `s2 :: … ``) or synthesized by a `#import c` foreign decl. A raw
/// name is exempt from the reserved-type-name binding check (issue 0089).
is_raw: bool = false,
};
pub const Param = struct {
@@ -307,6 +315,13 @@ pub const ConstDecl = struct {
name: []const u8,
type_annotation: ?*Node,
value: *Node,
/// Span of the constant's name token, for the reserved-type-name decl
/// diagnostic (issue 0089).
name_span: Span = .{ .start = 0, .end = 0 },
/// True when the constant NAME was written as a backtick raw identifier
/// (`` `s2 :: … ``). A raw name is exempt from the reserved-type-name
/// binding check (issue 0089).
is_raw: bool = false,
};
pub const VarDecl = struct {