Skip to content

Fix tasty applied type tree on bounds #4679

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ object TastyImpl extends scala.tasty.Tasty {
}

object Applied extends AppliedExtractor {
def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[TypeTree])] = x match {
def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])] = x match {
case x: tpd.AppliedTypeTree @unchecked => Some(x.tpt, x.args)
case _ => None
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/test/dotty/tools/dotc/FromTastyTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ class FromTastyTests extends ParallelTesting {

// MatchError in SymDenotation.sourceModule on a ThisType
"t3612.scala",

// Fails on MacOS
"annot-bootstrap.scala",
),
recompilationBlacklist = Set(
"annot-bootstrap.scala",
)
).checkCompile()
}
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/tasty/Tasty.scala
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ abstract class Tasty { tasty =>

val Applied: AppliedExtractor
abstract class AppliedExtractor {
def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[TypeTree])]
def unapply(x: TypeTree)(implicit ctx: Context): Option[(TypeTree, List[TypeOrBoundsTree])]
}

val Annotated: AnnotatedExtractor
Expand Down
4 changes: 2 additions & 2 deletions library/src/scala/tasty/util/ShowExtractors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty

private implicit class TypeTreeOps(buff: Buffer) {
def +=(x: TypeOrBoundsTree): Buffer = { visitTypeTree(x); buff }
def +=(x: Option[TypeTree]): Buffer = { visitOption(x, visitTypeTree); buff }
def ++=(x: List[TypeTree]): Buffer = { visitList(x, visitTypeTree); buff }
def +=(x: Option[TypeOrBoundsTree]): Buffer = { visitOption(x, visitTypeTree); buff }
def ++=(x: List[TypeOrBoundsTree]): Buffer = { visitList(x, visitTypeTree); buff }
}

private implicit class TypeOps(buff: Buffer) {
Expand Down
59 changes: 35 additions & 24 deletions library/src/scala/tasty/util/ShowSourceCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
printDefAnnotations(cdef)

val flags = cdef.flags
if (flags.isImplicit) this += "implicit "
if (flags.isFinal && !flags.isObject) this += "final "
if (flags.isCase) this += "case "

if (flags.isObject) this += "object " += name.stripSuffix("$")
else if (flags.isTrait) this += "trait " += name
else this += "class " += name

if (!flags.isObject) {
Expand All @@ -93,7 +95,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
this += " "
printTypeTree(tpt)
this += "["
printTypeTrees(targs, ", ")
printTypeOrBoundsTrees(targs, ", ")
this += "]"
if (args.nonEmpty) {
this += "("
Expand Down Expand Up @@ -157,6 +159,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
printDefAnnotations(vdef)

val flags = vdef.flags
if (flags.isImplicit) this += "implicit "
if (flags.isOverride) this += "override "

if (flags.isLazy) this += "lazy "
Expand Down Expand Up @@ -210,7 +213,8 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
printDefAnnotations(ddef)

val flags = ddef.flags
if (flags.isOverride) sb.append("override ")
if (flags.isImplicit) this += "implicit "
if (flags.isOverride) this += "override "

this += "def " += name
printTargsDefs(targs)
Expand Down Expand Up @@ -271,7 +275,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
case Term.TypeApply(fn, args) =>
printTree(fn)
this += "["
printTypeTrees(args, ", ")
printTypeOrBoundsTrees(args, ", ")
this += "]"

case Term.Super(qual, tptOpt) =>
Expand Down Expand Up @@ -451,12 +455,12 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
this
}

def printTypeTrees(typesTrees: List[TypeTree], sep: String): Buffer = {
def printSeparated(list: List[TypeTree]): Unit = list match {
def printTypeOrBoundsTrees(typesTrees: List[TypeOrBoundsTree], sep: String): Buffer = {
def printSeparated(list: List[TypeOrBoundsTree]): Unit = list match {
case Nil =>
case x :: Nil => printTypeTree(x)
case x :: Nil => printTypeOrBoundsTree(x)
case x :: xs =>
printTypeTree(x)
printTypeOrBoundsTree(x)
this += sep
printSeparated(xs)
}
Expand Down Expand Up @@ -496,34 +500,41 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty

def printTargDef(arg: TypeDef, isMember: Boolean = false): Buffer = {
val TypeDef(name, rhs) = arg
def printBounds(bounds: TypeBoundsTree): Buffer = {
val TypeBoundsTree(lo, hi) = bounds
lo match {
case TypeTree.Synthetic() =>
case _ =>
this += " >: "
printTypeTree(lo)
}
hi match {
case TypeTree.Synthetic() => this
case _ =>
this += " <: "
printTypeTree(hi)
}
}
this += name
rhs match {
case TypeBoundsTree(lo, hi) =>
lo match {
case TypeTree.Synthetic() => this
case _ =>
this += " >: "
printTypeTree(lo)
}
hi match {
case TypeTree.Synthetic() => this
case _ =>
this += " <: "
printTypeTree(hi)
}
case rhs @ TypeBoundsTree(lo, hi) => printBounds(rhs)
case rhs @ SyntheticBounds() =>
printTypeOrBound(rhs.tpe)
case rhs @ TypeTree.TypeLambdaTree(tparams, body) =>
def printParam(t: TypeOrBoundsTree): Unit = t match {
case t @ TypeBoundsTree(_, _) => printBounds(t)
case t @ TypeTree() => printTypeTree(t)
}
def printSeparated(list: List[TypeDef]): Unit = list match {
case Nil =>
case x :: Nil =>
val TypeDef(name, trhs) = x
this += name
printTypeOrBoundsTree(trhs)
printParam(trhs)
case x :: xs =>
val TypeDef(name, trhs) = x
this += name
printTypeOrBoundsTree(trhs)
printParam(trhs)
this += ", "
printSeparated(xs)
}
Expand Down Expand Up @@ -664,7 +675,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty

def printTypeOrBoundsTree(tpt: TypeOrBoundsTree): Buffer = tpt match {
case TypeBoundsTree(lo, hi) =>
this += " >: "
this += "_ >: "
printTypeTree(lo)
this += " <: "
printTypeTree(hi)
Expand Down Expand Up @@ -723,7 +734,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
case TypeTree.Applied(tpt, args) =>
printTypeTree(tpt)
this += "["
printTypeTrees(args, ", ")
printTypeOrBoundsTrees(args, ", ")
this += "]"

case TypeTree.Annotated(tpt, annot) =>
Expand Down
4 changes: 2 additions & 2 deletions tests/pos/i1181.decompiled
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** Decompiled from out/posTestFromTasty/pos/i1181/Test.class */
object Test {
def foo[M[_$1 >: scala.Nothing <: scala.Any]](x: M[scala.Int]): M[scala.Int] = x
type Alias[A >: scala.Nothing <: scala.Any] = scala.Tuple2[A, A]
def foo[M[_$1]](x: M[scala.Int]): M[scala.Int] = x
type Alias[A] = scala.Tuple2[A, A]
val x: Test.Alias[scala.Int] = scala.Tuple2.apply[scala.Int, scala.Int](1, 2)
Test.foo[Test.Alias](Test.x)
Test.foo[[A >: scala.Nothing <: scala.Any] => scala.Tuple2[A, A]](Test.x)
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/i2104b.decompiled
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** Decompiled from out/posTestFromTasty/pos/i2104b/Cons.class */
class Cons[H, T]() extends java.lang.Object
trait Cons[H, T]() extends java.lang.Object
object Cons {
def apply[H, T](h: H, t: T): Cons[H, T] = scala.Predef.???
def unapply[H, T](t: Cons[H, T]): scala.Option[Pair[H, T]] = scala.Predef.???
Expand Down
7 changes: 7 additions & 0 deletions tests/pos/t0905.decompiled
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** Decompiled from out/posTestFromTasty/pos/t0905/Test.class */
object Test {
trait A[T]() extends java.lang.Object
def f(implicit p: Test.A[_ >: scala.Nothing <: scala.Any]): scala.Null = null
implicit val x: Test.A[_ >: scala.Nothing <: scala.Any] = null
scala.Predef.println(Test.f(Test.x))
}
2 changes: 1 addition & 1 deletion tests/pos/tasty/definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ object definitions {
case Select(prefix: Term, name: String)
case Singleton(ref: Term)
case Refined(underlying: TypeTree, refinements: List[Definition])
case Applied(tycon: TypeTree, args: List[TypeTree])
case Applied(tycon: TypeTree, args: List[TypeTree | TypeBoundsTree])
case Annotated(tpt: TypeTree, annotation: Term)
case And(left: TypeTree, right: TypeTree)
case Or(left: TypeTree, right: TypeTree)
Expand Down