Skip to content

Keep foreign-only functions reachable and preserve host identifier boundaries - #1714

Merged
Lorenzobattistela merged 2 commits into
bendlang:mainfrom
oxura:fix/foreign-id-roots-20261018c
Oct 20, 2026
Merged

Lorenzobattistela merged 2 commits into
bendlang:mainfrom
oxura:fix/foreign-id-roots-20261018c

Conversation

@oxura

@oxura oxura commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

C effects can call functions that Bend never calls, or calls just once. Keep a native entry for those FID references instead of dropping or fusing it away. This rooting is C-only; JS FID stays a name string.

Host identifiers and JS private names stay untouched, without breaking C token pasting. Your d48dfb3 merge is included, and the guide prose is out.

All three fixtures pass --checkup, the interpreter, emitted JS and native C locally. Repo: 54/54. No private-cluster run claimed.

Fixes #1711
Fixes #1712

@Lorenzobattistela Lorenzobattistela self-assigned this Oct 19, 2026

@Lorenzobattistela Lorenzobattistela left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the fix works: foreign_only_fid is now emitted and runs, and namespaced FID(L.hidden) resolves. I merged main into the branch to resolve the conflict with #1653 (d48dfb3): ID_WORDS uses #1653's //.* comment rule, and effect_src splices C backslash-newlines when it caches the source, so the FID scan and the emitted C both see the spliced text. Please pull before pushing again.

Merged onto main d0d0c21: repo 54/54, ping 63/63, perf 124/124, safe 0 false rejects. Test is 1672/1673. Four things need to change before merge:

  1. tests/io/foreign_only_fid fails the test gate:

    FAIL io_foreign_only_fid [check]
      observed: Error: a foreign def without a .js import: answer
    

    The gate always checks and interprets through JS, so every effect test needs a .js twin, and this is the only C-only one. Please add foreign_only_fid.js. While there, please also add a test where hidden has exactly one Bend callsite (so it's fused into its caller) and is also called through FID. The PR fixes that case too (main fails at clang), but no test covers it.

  2. The # in the new lookbehind breaks C token pasting. This effect works on main and fails on the PR:

    #define ID_OF(x) x##CID(answer)
    ... io_eff(ID_OF(), answer_run);
    

    main prints 42; PR: error: call to undeclared function 'CID'. The # is only needed for JS private names, so please apply it only to the JS lane.

  3. The FID scan now also runs on the JS lane, where FID is just a name string. A .js effect that mentions FID(helper), where helper is a foreign def with only a .c import, now dies at build time: Error: a foreign def without a .js import: helper. The same program builds and prints 42 on main. The scan only needs to root FIDs for the C build.

  4. Please drop the guide/EFFECTS.md change; we keep guide prose out of fix PRs.

@oxura

oxura commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

Fetched your d48dfb3 merge first. I’m adding the JS twin and the fused-call regression, making the # boundary JS-only, and keeping FID rooting on the C lane. I’ll drop the guide prose too.

@oxura

oxura commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

Thanks — pushed 1873a49 on top of your d48dfb3 merge. The JS twin and single-call FID test are in, token-pasted CID works again in C, and a JS FID string no longer pulls in a C-only foreign def. guide/EFFECTS.md matches main again.

All three fixtures pass --checkup, the interpreter, emitted JS and native C locally; repo is 54/54. I haven’t run the private cluster gates.

@Lorenzobattistela
Lorenzobattistela force-pushed the fix/foreign-id-roots-20261018c branch from 1873a49 to 38c4f02 Compare October 20, 2026 13:20

@Lorenzobattistela Lorenzobattistela left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, all four points are fixed. I rebased your two commits onto main 642d8e1 (now 38c4f02) after #1786 freed comp.ts room, so please reset your local branch before pushing again.

On 642d8e1: repo 54/54 (comp.ts 65,221 / 66k), test 1691/1691, ping 63/63, safe 0 false rejects, perf matches main.

Two non-blocking notes for a follow-up:

  • The C scan roots every FID it sees, including the one in #ifdef FID(x), so that guard now always passes (main: false when x is not compiled in). Nothing in the repo uses #ifdef FID, but skipping FIDs on preprocessor lines would keep the guard meaningful.
  • The JS twins of foreign_fused_fid and foreign_only_fid return a constant, so only the C lane exercises FID.

@Lorenzobattistela
Lorenzobattistela merged commit 60ca80a into bendlang:main Oct 20, 2026
1 check passed
@oxura

oxura commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Thanks! I'll handle both notes in a separate follow-up on fresh main, leaving the old local branch alone.

nicolas-abril added a commit to nicolas-abril/bend that referenced this pull request Oct 20, 2026
- main_pure names an imported constructor or type through an alias, so
  the printer source parses (was `case lib2:Circ{f0}:`); the Array
  splice too. tests/show/imported_adt pins both.
- IO.print and IO.write on JS hold stdout off a terminal, as C's stdio
  does, and io_sync writes it before a wait, an error, an exit or at
  64 KiB; one TextEncoder. A depth-20 tree (20.9 MB) prints in 0.91 s
  (4.3 s before, 0.29 s on main).
- The C host Nat check is gone, as on main: tests/io/nat_host_bounds
  pins C taking 2^48 and 2^53 as words.
- turn_fits is back.
- A def an effect names with FID(..) is emitted on its own (bendlang#1714).
@Lorenzobattistela Lorenzobattistela mentioned this pull request Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CID scanning rewrites suffixes of legal host identifiers A function used only through foreign FID is not emitted

2 participants