Skip to content

Keep refinements in printed types - #256

Open
rochala wants to merge 3 commits into
mainfrom
scala-refinements
Open

rochala wants to merge 3 commits into
mainfrom
scala-refinements

Conversation

@rochala

@rochala rochala commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Closes #206.

Type and term refinements printed as their parent only, so Aux-style types lost the member they pin:

- implicit def toAlignOps[F[_], A](target: F[A])(implicit tc: Align[F]): Ops[F, A]
+ implicit def toAlignOps[F[_], A](target: F[A])(implicit tc: Align[F]): Ops[F, A] { type TypeClassType = Align[F] }

This builds on the backup-branch commit (d262e19) and fixes the two problems its review found:

  • Sibling references: def struct: { type A; def get: A } printed def get: RecThis.A. Dotty's TypeAssigner closes a refinement over itself (RecType.closeOver(… substThis(refineCls, rt.recThis))), so a RecThis prefix stands for the bare sibling name the source wrote. It now prints A. Dotty's own printer names the binder instead ({z1 => Object{type A; def get: z1.A}} in the 3.7.4 REPL); cellar follows the source here.
  • Object parent: type Tupled[F[_]] = { type Ap[X, Y] = F[(X, Y)] } printed = Object { … }. Dotty's Typer.typedRefinedTypeTree fills an omitted parent with Object, and scalac with AnyRef. The new helper isOmittedRefinementParent leaves a parent that dealiases to Object out. An explicitly written Object { … } can't be told apart once compiled, so it loses the Object too. Dotty's printer keeps it (Object{type Ap[X,Y] = …}).
  • Function types: [X] => F[X] => G[X] is stored as PolyFunction refined with apply, and so is a dependent (x: A) => x.T on FunctionN. As in dotty's RefinedPrinter (defn.isFunctionType → toTextMethodAsFunction), these print as functions, using the helper isRefinedFunction. Parameter names that Desugar.makePolyFunctionType invented (x$1, …) are left out, as written in source; dotty leaves them out only under capture checking. Written names stay: [X] => (fx: List[X], n: Int) => Option[X].
  • Spacing: dotty prints Ops[Int]{type TC = String}; cellar puts spaces around the braces, as the source does.

Benchmark side: the comparison now treats refinement members split by lines and by ; alike. Without that, every multi-member refinement counted as "still differs".

Tests: new fixtures cover a sibling reference (Scala 3 and Scala 2) and an Object-parent alias (Scala 3). Two more fixtures cover poly functions with invented and with written parameter names. Each refinement test fails with its fix disabled. Checked end to end with get-external on the fixtures and on cats' Align ops conversions.

Signature benchmark vs origin/main:

  • Scala 3: 106 changed (fixed: 103, regressed: 0, still differs: 3), 13643 unchanged
  • Scala 2: 105 changed (fixed: 100, regressed: 0, still differs: 5), 13539 unchanged
  • Java: 0 changed, 24772 unchanged

Still differs, out of scope:

🤖 Generated with Claude Code

https://claude.ai/code/session_01NKsT2pk4Cgn8JG8KsYEWoP

rochala and others added 3 commits October 21, 2026 16:58
`Ops[F, A] { type TypeClassType = Align[F] }` printed as `Ops[F, A]`, and an
`Aux` alias lost the type member it pins. Type and term refinements now print
their members. A member naming a sibling prints its bare name instead of
tasty-query's RecThis, and a refinement written without a parent no longer
prints the Object the compiler fills in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NKsT2pk4Cgn8JG8KsYEWoP
TASTy stores `[X] => F[X] => G[X]` as PolyFunction refined with its apply;
it printed as that refinement. As dotty's RefinedPrinter does, it now prints
as a function, with the parameter names Desugar invented left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NKsT2pk4Cgn8JG8KsYEWoP

This branch has not been deployed

No deployments
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.

Scala: refinements are dropped from printed types

1 participant