Closed
Description
The following code compiles fine with Scalac, but fails in Dotty. If the commented version of ~++
is used, everything is fine.
trait Rule[-In, +A] extends (In => A) {
def flatMap[In2 <: In, B](fa2ruleb: A => Rule[In2, Seq[B]]): Rule[In, Seq[B]] = ???
def map[B](fa2b: A => B): Rule[In, B] = ???
def ~++[In2, B >: A](next: => Rule[In2, Seq[B]]) = for (a <- this; b <- next) yield a :: b.toList
// def ~++[In2, B >: A](next: => Rule[In2, Seq[B]]): Rule[In, Seq[B]] = for (a <- this; b <- next) yield a :: b.toList
}
class SeqRule {
type S
type A
def * : Rule[S, List[A]] = ???
def +(rule: Rule[S, A]) : Rule[S, Seq[A]] = rule ~++ *
}
The cause is that ~++
gets an "ill" type that refers to the local variable b
(see below at bottom). The check is not handled by Typer#escapingRefs
. I tried to modify TypeOps#simplify
to simplify TypeRef(TermRef(NoPrefix,b),scala$collection$TraversableOnce$$A)
to just ParamRef(B)
, but didn't succeed.
PolyType(
List(In2, B),
List(TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix,scala)),Nothing), TypeRef(ThisType(TypeRef(NoPrefix,scala)),Any)), TypeBounds(TypeRef(TermRef(NoPrefix,rule),Rule$$A), TypeRef(ThisType(TypeRef(NoPrefix,scala)),Any))),
MethodType(
List(next),
List(
ExprType(
RefinedType(
RefinedType(
TypeRef(ThisType(TypeRef(NoPrefix,<empty>)),Rule),
Rule$$In,
TypeAlias(ParamRef(In2), -1)
),
Rule$$A,
TypeAlias(
RefinedType(
TypeRef(ThisType(TypeRef(NoPrefix,collection)),Seq),
scala$collection$Seq$$A,
TypeAlias(ParamRef(B), 1)
),
1))
)
),
RefinedType(
RefinedType(
TypeRef(ThisType(TypeRef(NoPrefix,<empty>)),Rule),
Rule$$In,
TypeAlias(
TypeRef(TermRef(NoPrefix,rule),Rule$$In),
-1)
),
Rule$$A,
TypeAlias(
RefinedType(
TypeRef(ThisType(TypeRef(NoPrefix,collection)),Seq),
scala$collection$Seq$$A,
TypeAlias(TypeRef(TermRef(NoPrefix,b),scala$collection$TraversableOnce$$A), 1) <=== b !!
),
1)
)
)
)
The expanded version of ~++
looks like follows:
def ~++[In2, B >: A](next: => Rule[In2, Seq[B]]):
Rule[In, scala.collection.Seq[B]]
=
this.flatMap[Nothing^, B^](
{
def $anonfun(a: A): Rule[Nothing^, scala.collection.Seq[B^]] =
next.map[scala.collection.immutable.List[B]^](
{
def $anonfun(b: scala.collection.Seq[B]):
scala.collection.immutable.List[B]
=
{
val $1$: A = a
b.toList.::[B^]($1$)
}
closure($anonfun)
}
)
closure($anonfun)
}
)
}
Note: this test case is a minimized version from the library json4s.