Skip to content

Allow global language imports in REPL and snippet compiler - #25458

Merged
bracevac merged 5 commits into
scala:mainfrom
dotty-staging:fix-experimental-repl-import-v2
Mar 11, 2026
Merged

Allow global language imports in REPL and snippet compiler#25458
bracevac merged 5 commits into
scala:mainfrom
dotty-staging:fix-experimental-repl-import-v2

Conversation

@bracevac

@bracevac bracevac commented Mar 8, 2026

Copy link
Copy Markdown
Member

Previously, import language.experimental.captureChecking (and related global language imports) were rejected in the REPL and snippet compiler because they appeared in nested scopes rather than at the toplevel.

This change takes a structural approach to fix both contexts:

  • REPL: Forward outermost through blockStatSeq in Interactive mode so the parser treats REPL-level imports as toplevel. After a successful compile, propagate global language imports to rootCtx as -language: settings so subsequent inputs can parse CC syntax (e.g. ^).

  • Snippet compiler: Extract global language imports from snippet body and place them before the object Snippet {} wrapper, making them genuine toplevel imports.

Fixes #16250

How much have your relied on LLM-based tools in this contribution?

Used Claude extensively to analyze the problem and iterate on the solution.

How was the solution tested?

There are REPL and snippet compiler tests. I also verified manually
within the REPL that the top-level CC import works.
Updated some snippets in the CC language ref to verify that the snippet compilation
works as well.

@bracevac

bracevac commented Mar 8, 2026

Copy link
Copy Markdown
Member Author

This is an alternative to #25415

@bracevac
bracevac force-pushed the fix-experimental-repl-import-v2 branch 4 times, most recently from cad95f0 to 985919c Compare March 8, 2026 19:27
Comment thread repl/test/dotty/tools/repl/ReplCompilerTests.scala Outdated
Comment thread docs/_docs/reference/experimental/capture-checking/safe.md Outdated
Comment thread repl/src/dotty/tools/repl/ReplDriver.scala Outdated
Previously, `import language.experimental.captureChecking` (and related
global language imports) were rejected in the REPL and snippet compiler
because they appeared in nested scopes rather than at the toplevel.

This change takes a structural approach to fix both contexts:

- REPL: Forward `outermost` through `blockStatSeq` in Interactive mode
  so the parser treats REPL-level imports as toplevel. After a successful
  compile, propagate global language imports to `rootCtx` as `-language:`
  settings so subsequent inputs can parse CC syntax (e.g. `^`).

- Snippet compiler: Extract global language imports from snippet body and
  place them before the `object Snippet {}` wrapper, making them genuine
  toplevel imports.

Fixes scala#16250
Move propagateLanguageImports before compile so that newRun derives
the state context from an already-updated rootCtx, eliminating the
post-compilation settings sync.
Move the set of global language features (pureFunctions, captureChecking,
separationChecking, safe) into Feature.globalLanguageImports so that
ReplDriver and WrappedSnippet derive from a single source of truth.
@bracevac
bracevac force-pushed the fix-experimental-repl-import-v2 branch from a14790e to b81511e Compare March 11, 2026 10:43
@natsukagami

Copy link
Copy Markdown
Contributor

Function types seem to have wrong capture sets printed:

scala> import language.experimental.captureChecking

scala> def f(x: () -> Unit): Unit = x()
def f(x: () -> Unit): Unit

scala> class A extends caps.SharedCapability
// defined class A

scala> val t = () => { a; () }
1 warning found
-- [E129] Potential Issue Warning: ---------------------------------------------
1 |val t = () => { a; () }
  |                ^
  |                A pure expression does nothing in statement position
  |
  | longer explanation available when compiling with `-explain`
val t: () -> Unit = Lambda/0x00007f7cc067c208@49ed96e3

scala> f(t)
-- [E007] Type Mismatch Error: -------------------------------------------------
1 |f(t)
  |  ^
  |  Found:    (t : () ->{a} Unit)
  |  Required: () -> Unit
  |
  |  Note that capability `a` cannot flow into capture set {}.
  |
  | longer explanation available when compiling with `-explain`
1 error found

@bracevac

bracevac commented Mar 11, 2026

Copy link
Copy Markdown
Member Author

Yikes! I didn't realize how broken the CC pretty printing was. Maybe this is worth its own follow-up PR?

Edit: It was straightforward to fix.

@bracevac
bracevac force-pushed the fix-experimental-repl-import-v2 branch from db37130 to daa49e3 Compare March 11, 2026 14:20
The REPL rendered types at `typerPhase.next`, before capture checking
runs, so inferred capture sets were invisible. When CC is enabled, render
at `checkCapturesPhase` instead where Setup has added `CaptureAnnotations`
and the `CapturingType` extractor works.

Additionally, the local defs in renderDefinitions captured the outer
given Context instead of receiving the phase-adjusted context from
atPhase. Adding (using Context) parameters fixes the propagation.

Also route the `CaptureAnnotation` fallback in `PlainPrinter` through
`toTextCapturing` so function types render as () ->{a} Unit rather
than (() -> Unit)^{a}.
@bracevac
bracevac force-pushed the fix-experimental-repl-import-v2 branch from daa49e3 to 3b55f53 Compare March 11, 2026 14:54

@natsukagami natsukagami left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nicer error messages too 🎉

@bracevac
bracevac enabled auto-merge (squash) March 11, 2026 15:53
@bracevac
bracevac merged commit df5f612 into scala:main Mar 11, 2026
64 checks passed
@bracevac
bracevac deleted the fix-experimental-repl-import-v2 branch March 11, 2026 16:44
@WojciechMazur WojciechMazur added this to the 3.8.4 milestone Mar 31, 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.

REPL : pureFunctions and captureChecking fail with "language import only allowed at toplevel"

6 participants