Skip to content

feat: func-signature type aliases #2541

Description

@SchoolyB

Typed func signatures are verbose at every use site, and the verbosity compounds because the same signature is repeated across parameters, struct fields, and locals:

do each(arr [int], f func(int)) { }
do fold(arr [int], init int, f func(int, int) -> int) -> int { }

const Wrapper struct {
    on_start func(int) -> int
    on_error func(string, int) -> bool
}

Naming the signature once removes the clutter without erasing the signature from the type, so argument counts, argument types, and return types stay checked:

alias Visitor = func(int)
alias Folder  = func(int, int) -> int
alias Handler = func(int) -> int
alias ErrHook = func(string, int) -> bool

do each(arr [int], f Visitor) { }
do fold(arr [int], init int, f Folder) -> int { }

const Wrapper struct {
    on_start Handler
    on_error ErrHook
}

This is how the languages Grayscale draws from solve it — Go's type Handler func(int) int, Odin's Proc :: proc(int) -> int, Rust's type Op = fn(i32) -> i32. None of them offers a signature-erasing function type, because it costs call-site checking and return-type inference.

Current state

Most of this already works and is undocumented. parse_alias_declaration calls parse_complex_type, which encodes func(...) as the flat "func(int)->int" type-name string the type system already uses, so aliases picked up func signatures for free. Verified working on HEAD:

  • func alias as a parameter type, called through the parameter
  • func alias as a standalone const variable type
  • void signatures (alias Sink = func(int)) and multi-parameter signatures (alias Pair = func(int, string) -> bool)
  • type_of() returns the underlying signature (func(int)), consistent with aliases being erased at compile time
  • signature mismatch through an alias reports E3066 and prints the underlying signature in the message

What does not work is the struct-field position, which is one of the two places the clutter is worst. That defect is filed separately as a bug; this issue is not complete until it lands.

Scope

1. STANDARD.md §3.5

The "Can alias" list reads as exhaustive — "primitives, structs, enums, arrays ([T]), maps (map[K:V]), and pointers (^T)" — and omits func signatures, which is why the capability is invisible. Add them with an example. State explicitly whether the aliasable and non-aliasable lists are exhaustive; a reader currently cannot tell whether an omission means unsupported or unmentioned.

2. STANDARD.md §7.6

Cross-reference aliasing from the section that introduces func signatures, since that is where a reader feeling the clutter is standing. §7.6.2 (parameters) and §7.6.4 (struct fields) are the two positions worth naming. §7.6.4 requires a typed signature for struct fields — state that an alias of a typed signature satisfies that requirement.

3. Interaction with the bare-func rules

§7.6.3 disallows typed func signatures as array element types ([func(int)->int]), directing users to [func] or [func, N]. An alias of a func signature is a typed signature, so [Handler] must be rejected by the same rule and with the same diagnostic. It currently fails with a confusing E3001 type mismatch instead — this is the general composite-position alias defect, tracked separately, and this issue only needs the resulting behavior documented once that lands.

4. Language rule to record

An alias of a func signature is interchangeable with the signature everywhere the signature is legal, and illegal everywhere the signature is illegal. No new positions become legal because a name was put in front of the type.

Tests

Pass coverage:

  • func alias as a parameter type, called through the parameter
  • func alias as a struct field type, both struct-literal and new() pointer forms
  • void signature alias and multi-parameter signature alias
  • alias chaining (alias A = func(int) -> int then alias B = A)
  • type_of() through a func alias
  • a func alias and its literal signature used interchangeably in the same program

Fail coverage:

  • mismatched reference assigned through a func alias reports E3066
  • [Handler] as an array element type is rejected by the §7.6.3 rule
  • bare func as a struct field type still reports E3130

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or requesttypecheckerRelated to type checking and validation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions