Skip to content

fix(hy-syntax,hy-emit): keep fn-type result parsing on same line and support unnamed/parenthesized signatures (fixes #727) - #735

Open
aazminu wants to merge 2 commits into
limitlessprojects:mainfrom
aazminu:fix-727-fn-type-results
Open

aazminu wants to merge 2 commits into
limitlessprojects:mainfrom
aazminu:fix-727-fn-type-results

Conversation

@aazminu

@aazminu aazminu commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #727.

Previously, Parser::parse_type's Tok::Kw("fn") arm collected result types via an unguarded while self.is_type_start() loop that crossed line boundaries, and used parse_params() (which requires a leading parameter identifier) for TypeExpr::Fn parameter lists:

  1. A local var cb fn() int followed on the next line by fmt.println(cb == nil) or f(1) absorbed the following line's leading identifier/type into TypeExpr::Fn.results, either swallowing the next statement or turning it into a multi-return func() int, ... Go syntax error.
  2. In a struct declaration, any field declared after a fn(...)-typed field (e.g. on_event fn(int) bool followed by name string) had its field name and type absorbed as extra return types of the fn field, erasing the subsequent struct field.
  3. Unnamed parameter types in fn(int) bool or fn(*int, []string) (int, error) were either stored in Param.name with an empty Param.ty (causing hy-emit to emit a trailing space func(int ) and bypassing checker passes on Param.ty) or rejected when starting with */[/<-.
  4. Multi-result function types in hy-emit (TypeExpr::Fn with results.len() > 1) were emitted without parentheses (func() int, error) instead of valid Go func() (int, error).

Changes

  • compiler/crates/hy-syntax/src/parser.rs:
    • Guard TypeExpr::Fn result parsing with self.same_line_as_prev() so identifiers/types on following lines (next statements or subsequent struct fields) are never absorbed into results.
    • Support parenthesized result lists on the same line (if self.same_line_as_prev() && self.at_punct("(")) via parse_results().
    • Add parse_fn_type_params() (and align parse_results()) so unnamed parameter types (fn(int), fn(*int, []string, map[string]int)) populate Param.ty with an empty Param.name while named parameter lists (fn(a int, b string)) continue to populate both Param.name and Param.ty.
  • compiler/crates/hy-emit/src/lib.rs:
    • Format unnamed TypeExpr::Fn parameters without a leading/trailing space, parenthesize multi-value TypeExpr::Fn result lists (func(...) (T1, T2)), and return "nil" as the zero value for TypeExpr::Fn.
  • compiler/crates/hy-check/src/buildable.rs:
    • Preserve Some(params.len()) in kind_of_ty_with_subst for TypeExpr::Fn.
  • Tests:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant