diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala index e8e5bd926ca3..b9efdf59146d 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala @@ -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 } diff --git a/compiler/test/dotty/tools/dotc/FromTastyTests.scala b/compiler/test/dotty/tools/dotc/FromTastyTests.scala index 9d1c5d13a23e..6c992a0be945 100644 --- a/compiler/test/dotty/tools/dotc/FromTastyTests.scala +++ b/compiler/test/dotty/tools/dotc/FromTastyTests.scala @@ -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() } diff --git a/library/src/scala/tasty/Tasty.scala b/library/src/scala/tasty/Tasty.scala index d5c67a1ff65f..237d962be2a8 100644 --- a/library/src/scala/tasty/Tasty.scala +++ b/library/src/scala/tasty/Tasty.scala @@ -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 diff --git a/library/src/scala/tasty/util/ShowExtractors.scala b/library/src/scala/tasty/util/ShowExtractors.scala index 030c6ccc33fd..6f2b0e83c313 100644 --- a/library/src/scala/tasty/util/ShowExtractors.scala +++ b/library/src/scala/tasty/util/ShowExtractors.scala @@ -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) { diff --git a/library/src/scala/tasty/util/ShowSourceCode.scala b/library/src/scala/tasty/util/ShowSourceCode.scala index 44e910c524a0..d28cad8b4f7d 100644 --- a/library/src/scala/tasty/util/ShowSourceCode.scala +++ b/library/src/scala/tasty/util/ShowSourceCode.scala @@ -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) { @@ -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 += "(" @@ -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 " @@ -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) @@ -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) => @@ -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) } @@ -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) } @@ -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) @@ -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) => diff --git a/tests/pos/i1181.decompiled b/tests/pos/i1181.decompiled index a88d47e927ff..fb585ba66b9d 100644 --- a/tests/pos/i1181.decompiled +++ b/tests/pos/i1181.decompiled @@ -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) diff --git a/tests/pos/i2104b.decompiled b/tests/pos/i2104b.decompiled index 37dfebabc7e0..46201c2fd6ff 100644 --- a/tests/pos/i2104b.decompiled +++ b/tests/pos/i2104b.decompiled @@ -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.??? diff --git a/tests/pos/t0905.decompiled b/tests/pos/t0905.decompiled new file mode 100644 index 000000000000..dba33a22a1ba --- /dev/null +++ b/tests/pos/t0905.decompiled @@ -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)) +} diff --git a/tests/pos/tasty/definitions.scala b/tests/pos/tasty/definitions.scala index edc266448b22..a90e6912e7c3 100644 --- a/tests/pos/tasty/definitions.scala +++ b/tests/pos/tasty/definitions.scala @@ -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)