Skip to content

compiler: add --allow-module-private-access to bypass module-private (#1454)#1458

Open
mbouaziz wants to merge 1 commit into
mainfrom
bypass-module-private
Open

compiler: add --allow-module-private-access to bypass module-private (#1454)#1458
mbouaziz wants to merge 1 commit into
mainfrom
bypass-module-private

Conversation

@mbouaziz

@mbouaziz mbouaziz commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Closes #1454.

Adds --allow-module-private-access, a compile flag that permits reaching module-private elements from outside their module. The motivation is white-box tests: with module-private enforced (#1343), test code in a different module can no longer poke at internals without exposing them in the public API. Off by default, so enforcement stays on everywhere else.

Implementation

The flag threads from Config through the front end to the one place that decides:

Config.bypass_module_private
  → getOrInitializeBackend → makeOuterIst → type_program
  → SkipExpand.program → Env.allowPrivateAccess
  → check_module: the private-access arm returns void instead of erroring

check_module already special-cases same-module access; this adds one more guard arm:

| (true, _) if (env.allowPrivateAccess) -> void

Notes:

  • The front end is otherwise config-free, so the flag is threaded explicitly rather than read from a global. Env.allowPrivateAccess rides env with { … } unchanged, so it reaches every check_module on the compile path (which all flow from the single expandEnv).
  • Works in batch mode too: Config.withUnit uses this with { … }, so the field is inherited by per-unit configs.
  • element_privacy and the symbol table are untouched — only the reporting is gated, so nothing else changes.

Verification

  • Without the flag, M.secret() on a private fun secret in another module errors as before; with --allow-module-private-access it compiles and runs.
  • Compiler test suite: all behavioural tests pass, and the flag defaults off so flag-off behaviour is byte-identical to main. (Locally one meta-test, CompilerVersionCheck, tripped on a stale skc version-stamp left by iterative rebuilds; a clean rebuild makes skc --version match HEAD again, so CI's fresh build passes it.)

No harness test is added: the invalid/valid test framework compiles every unit with a fixed skc command (no per-test flags), so there's no place to exercise a custom flag. Happy to add one if a per-test-flags mechanism is wanted.

Design note

This is the "global compile flag" option from the discussion on #1454 — the simplest, bluntest one. The alternatives (white-box tests in a same-module file, which already works since module-private is module-scoped; or an explicit per-module "friend" annotation) stay open; this flag doesn't preclude them. Flag name is easy to change if you'd prefer something like --unsafe-allow-private.

— Claude Opus 4.8 (1M context)

An escape hatch for reaching module-`private` elements from outside their
module — primarily for white-box tests that need to poke at internals
without exposing them in the public API. Off by default, so enforcement
stays on everywhere else.

The flag threads from Config through the front end (getOrInitializeBackend
-> makeOuterIst -> type_program -> SkipExpand.program -> Env.allowPrivateAccess)
to check_module, whose private-access arm returns void instead of erroring
when it is set. `Env.allowPrivateAccess` rides `env with { ... }` so it
reaches every check_module on the compile path; Config.withUnit inherits the
field via `this with { ... }`, so it works in batch mode too.

Closes #1454.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mbouaziz

Copy link
Copy Markdown
Contributor Author

Not merging as the code is not the nicest.
Keeping this just in a case someone needs to compile something under the old (disabled) privacy checks or wants to use it for tests even though they are other options

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.

compiler: add an option to bypass module-private enforcement

1 participant