You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix regressions: use typer skolems as inline proxy's type
Fixes#26153Fixes#26031Fixes#26624
**problem**
When an inline expansion has a type that depends on one of
the inline method arguments, and that argument is not stable,
there's a type mismatch error on inline function call.
For example,
```scala
trait Mon[F[_]] { type Arg }
class Wrap[F[_], A]:
inline def apply[T](inline f: A => T): F[T] = ...
inline def async[F[_]](using am: Mon[F]) =
new Wrap[F, am.Arg]
object Test:
val r = async[[A] =>> (String, A)](_ => 42)
// given TupleMon[E] extends Mon[[A] ==> (E, A)]
```
The result of `async` depends on the argument `am`: `Wrap[F, am.Arg]`.
At the call site, the given argument for `am` is not a stable path. When
`TypeAssigner` computes the dependent result type, it skolemizes that argument.
So the inline call is typed as something like:
`Wrap[[A] =>> (String, A), ?1.Arg]` where:
`?1` is some value of type `Mon[[A] =>> (String, A)]`.
On the other hand, `Inlining` creates a runtime proxy for the same
arugment: `am$proxy` = <actual given>.
When the proxy is typed as `am$proxy: Mon[[A] ==> (String, A)]`,
then types in the expanded tree is like `am$proxy.Arg`.
While the call tree was typed as `?1.Arg`.
As a result, compile fails:
```scala
val r = async[[A] =>> (String, A)](_ => 42)
^^^^^^^
Found: ?1.Arg => Int
Required: am$proxy1.Arg => Int
where: ?1 is an unknown value of type Mon[[A] =>> (String, A)]
```
The same root issue also causes regression #26031
```scala
trait Ctx[F[_]]
trait Mon[F[_]]:
type Context <: Ctx[F]
object Mon:
type Aux[F[_], C <: Ctx[F]] = Mon[F] { type Context = C }
class Wrap[F[_], C <: Ctx[F]](using val am: Mon.Aux[F, C])
transparent inline def doIt[F[_]](using am: Mon[F]) =
new Wrap(using am)
```
The call tree fixes `C = ?1.Context`, so the expansion needs an argument of type
`Mon.Aux[F, ?1.Context]`. A proxy typed only as `Mon[F]` does not prove that
its `Context` member is `?1.Context`.
**Fix**
The idea is Use the skolem created by typer as the type of the inline proxy.
`val am$proxy: ?1 = <actual given>.asInstanceOf[?1]`.
The runtime value is still the proxy, but its type-level prefix is now
the same skolem generated by typer.
This fixes the mismatch in #26153, and also fixes#26031 because the proxy
term itself now has the skolem type.
The idea is from:
> I was wondering it would be great if we can use something like `Wrap[F, m.Arg] forSome { val m: Mon[F] }` instead of `?`, which is too coarse. And ... I realized that typer already uses skolem type `?1.Arg` when the result type is dependent.
> #26033 (comment)
---
This commit also dealias `NamedTypes` when homogenizing for `-Ytest-pickler`,
otherwise, skolem before pickle vs unpickled has different type printing
`Predef.String` vs `String` (tests/run/i14020)
**note**
Original PR #26033
was to special-case `selectionType` for an `Inlined` receiver.
if the saved type of the `Inlined` tree was avoided to `?`, use the
expansion's type instead.
That can fix the immediate receiver mismatch, but it is workaround-ish. It
recovers `am$proxy.Arg` after avoidance, which isn't right.
while typer already had the better stable prefix `?1.Arg`.
Another fix I tried was to rewrite only type positions:
`am$proxy.Arg` => `?1.Arg`
This helps #26153, where the mismatch is in the expanded type. But it does not
fix#26031. A term with type `Mon[F]` still does not conform, it's
required refinements.
0 commit comments