Skip to content

Fixes #16018: Existential widening for wildcard arguments#26152

Open
He-Pin wants to merge 1 commit into
scala:mainfrom
He-Pin:add-i16018-tests
Open

Fixes #16018: Existential widening for wildcard arguments#26152
He-Pin wants to merge 1 commit into
scala:mainfrom
He-Pin:add-i16018-tests

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

@He-Pin He-Pin commented May 23, 2026

Fixes #16018.

TypeComparer.compareCaptured consulted only the declared parameter bound (paramBounds(tparam).hi/.lo), which collapses to Any/Nothing for unconstrained parameters, so F[? <: hi] <: F[hi] (covariant) and G[? >: lo] <: G[lo] (contravariant) were rejected. The fix consults the wildcard's own bound, intersected (resp. unioned) with the declared bound for soundness. Recursive (F-bounded) declared bounds stay on the conservative path to avoid forcing paramBounds(tparam) to loop.

Tests: tests/pos/i16018.scala, tests/pos/i16018b.scala, tests/neg/i16018.scala.

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

Extensively, for the fix and test.

How was the solution tested?

Covered by tests from the issue and some more tests

@He-Pin He-Pin marked this pull request as draft May 23, 2026 16:05
@He-Pin He-Pin force-pushed the add-i16018-tests branch from 98b1671 to b45a8f5 Compare May 23, 2026 17:21
@He-Pin He-Pin force-pushed the add-i16018-tests branch from b45a8f5 to 5ccc481 Compare May 23, 2026 20:27
@He-Pin He-Pin changed the title Pin partial progress of #16018 with directional pos/neg tests Fixes #16018: Existential widening for wildcard arguments May 23, 2026
@He-Pin
Copy link
Copy Markdown
Contributor Author

He-Pin commented May 23, 2026

This fix will facilitate cross-compilation between Scala 2.13 and Scala 3, especially for Java users.

@He-Pin He-Pin force-pushed the add-i16018-tests branch from 5ccc481 to ca8701f Compare May 23, 2026 20:51
Comment thread tests/pos/i16018c.scala Outdated
@He-Pin He-Pin force-pushed the add-i16018-tests branch from ca8701f to d43b013 Compare May 23, 2026 21:14
Comment thread tests/neg/i16018c.scala Outdated
@He-Pin He-Pin force-pushed the add-i16018-tests branch from d43b013 to dc0d66b Compare May 23, 2026 21:34
@He-Pin He-Pin marked this pull request as ready for review May 23, 2026 21:38
@He-Pin He-Pin force-pushed the add-i16018-tests branch from dc0d66b to b952dfd Compare May 23, 2026 21:42
@He-Pin He-Pin marked this pull request as draft May 23, 2026 23:25
@He-Pin He-Pin marked this pull request as ready for review May 23, 2026 23:46
@He-Pin He-Pin marked this pull request as draft May 25, 2026 06:10
@He-Pin He-Pin marked this pull request as ready for review May 25, 2026 16:42
@He-Pin He-Pin force-pushed the add-i16018-tests branch from 1f58a30 to 1605f0f Compare May 28, 2026 05:40
@Gedochao Gedochao requested a review from bracevac May 28, 2026 06:51
Copy link
Copy Markdown
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

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

Please don't inundate reviewers with tons of AI-slop generated stuff. You are imposing with this on my valuable time. Please, next time pre-digest the material and present only the relevant points in a concise fashion.

Comment thread compiler/src/dotty/tools/dotc/core/TypeComparer.scala Outdated
Comment thread compiler/src/dotty/tools/dotc/core/TypeComparer.scala Outdated
Comment thread compiler/src/dotty/tools/dotc/core/TypeComparer.scala Outdated
@odersky odersky assigned He-Pin and unassigned odersky and bracevac May 28, 2026
@He-Pin He-Pin marked this pull request as draft May 29, 2026 06:06
He-Pin added a commit to He-Pin/scala3 that referenced this pull request May 29, 2026
Motivation:
PR scala#26152 review asked for a narrower recursive-bound guard in
TypeComparer.compareCaptured: removing the early broad guard that
bypassed capture conversion, replacing the lazy val cache with a def,
and checking only the bound the branch actually consults.

Modification:
- compareCaptured: drop the early `if hasRecursiveParamBounds(tparam)`
  guard so capture conversion runs unconditionally as before.
- Replace `lazy val recursiveParamBounds` / `def hasRecursiveParamBounds`
  with a single per-call `def hasRecursiveBound(bound, tparam)` walked
  over the relevant half only (`tparam.info.bounds.hi` for v > 0,
  `.lo` for v < 0).
- tests/neg/i16018d.scala: rewrite the F-bounded case to nest under a
  covariant container so capture conversion does not apply and the
  existential-widening branch is the one that runs, exercising the
  per-bound guard directly.

Result:
Net -22 lines in TypeComparer. The guard is per-bound and called only
when needed. Capture conversion runs unconditionally and produces the
sound path-dependent typed tree for stable LHS (which Ycheck:all
accepts) — the previous broad guard was over-restrictive.

References: scala#26152
@He-Pin He-Pin force-pushed the add-i16018-tests branch from 6c8fd81 to 6c93a8f Compare May 29, 2026 09:08
`TypeComparer.compareCaptured` consulted only the declared parameter
bound, which collapses to `Any`/`Nothing` for unconstrained parameters,
so `F[? <: hi] <: F[hi]` (covariant) and `G[? >: lo] <: G[lo]`
(contravariant) were rejected. Consult the wildcard's own bound,
intersected (resp. unioned) with the declared bound for soundness.
Recursive declared bounds stay on the conservative path to avoid forcing
`paramBounds(tparam)` to loop.
@He-Pin He-Pin force-pushed the add-i16018-tests branch from 6c93a8f to dbf7bcb Compare May 29, 2026 09:41
@He-Pin He-Pin marked this pull request as ready for review May 29, 2026 11:52
@He-Pin He-Pin requested a review from odersky May 29, 2026 18:41
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.

Type computed to any, works in Scala 2

3 participants