Skip to content

Commit 76b110b

Browse files
Merge pull request #4601 from dotty-staging/fix-synthetic-type-bounds
Fix synthetic type bounds in Tasty reflect
2 parents 78a5e09 + 78e4ed7 commit 76b110b

File tree

8 files changed

+102
-13
lines changed

8 files changed

+102
-13
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ object TastyImpl extends scala.tasty.Tasty {
538538

539539
object Synthetic extends SyntheticExtractor {
540540
def unapply(x: TypeTree)(implicit ctx: Context): Boolean = x match {
541-
case Trees.TypeTree() => true
541+
case x @ Trees.TypeTree() => !x.tpe.isInstanceOf[Types.TypeBounds]
542542
case _ => false
543543
}
544544
}
@@ -610,10 +610,10 @@ object TastyImpl extends scala.tasty.Tasty {
610610

611611
// ----- TypeBoundsTrees ------------------------------------------------
612612

613-
type TypeBoundsTree = tpd.TypeBoundsTree
613+
type TypeBoundsTree = tpd.Tree
614614

615615
def TypeBoundsTreeDeco(x: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI {
616-
def tpe(implicit ctx: Context): TypeBounds = x.tpe.bounds
616+
def tpe(implicit ctx: Context): TypeBounds = x.tpe.asInstanceOf[Types.TypeBounds]
617617
}
618618

619619
def typeBoundsTreeClassTag: ClassTag[TypeBoundsTree] = implicitly[ClassTag[TypeBoundsTree]]
@@ -625,6 +625,13 @@ object TastyImpl extends scala.tasty.Tasty {
625625
}
626626
}
627627

628+
object SyntheticBounds extends SyntheticBoundsExtractor {
629+
def unapply(x: TypeBoundsTree)(implicit ctx: Context): Boolean = x match {
630+
case x @ Trees.TypeTree() => x.tpe.isInstanceOf[Types.TypeBounds]
631+
case _ => false
632+
}
633+
}
634+
628635
// ===== Types ====================================================
629636

630637
type TypeOrBounds = Types.Type

library/src/scala/tasty/Tasty.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,10 @@ abstract class Tasty { tasty =>
388388

389389
def unapply(x: TypeTree)(implicit ctx: Context): Boolean
390390

391+
/** TypeTree containing an inferred type */
391392
val Synthetic: SyntheticExtractor
392393
abstract class SyntheticExtractor {
394+
/** Matches a TypeTree containing an inferred type */
393395
def unapply(x: TypeTree)(implicit ctx: Context): Boolean
394396
}
395397

@@ -456,6 +458,13 @@ abstract class Tasty { tasty =>
456458
def unapply(x: TypeBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)]
457459
}
458460

461+
/** TypeBoundsTree containing an inferred type bounds */
462+
val SyntheticBounds: SyntheticBoundsExtractor
463+
abstract class SyntheticBoundsExtractor {
464+
/** Matches a TypeBoundsTree containing inferred type bounds */
465+
def unapply(x: TypeBoundsTree)(implicit ctx: Context): Boolean
466+
}
467+
459468
// ===== Types ====================================================
460469

461470
type TypeOrBounds

library/src/scala/tasty/util/ShowExtractors.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
112112
this += "TypeTree.Annotated(" += arg += ", " += annot += ")"
113113
case TypeBoundsTree(lo, hi) =>
114114
this += "TypeBoundsTree(" += lo += ", " += hi += ")"
115+
case SyntheticBounds() =>
116+
this += s"SyntheticBounds()"
115117
}
116118

117119
def visitCaseDef(x: CaseDef): Buffer = {
@@ -188,7 +190,8 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
188190
case Type.PolyType(argNames, argBounds, resType) =>
189191
this += "Type.PolyType(" ++= argNames += ", " ++= argBounds += ", " += resType += ")"
190192
case Type.TypeLambda(argNames, argBounds, resType) =>
191-
this += "Type.TypeLambda(" ++= argNames += ", " ++= argBounds += ", " += resType += ")"
193+
// resType is not printed to avoid cycles
194+
this += "Type.TypeLambda(" ++= argNames += ", " ++= argBounds += ", _)"
192195
case TypeBounds(lo, hi) =>
193196
this += "TypeBounds(" += lo += ", " += hi += ")"
194197
case NoPrefix() =>

library/src/scala/tasty/util/ShowSourceCode.scala

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,9 +486,11 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
486486
this += " <: "
487487
printTypeTree(hi)
488488
}
489-
case tpt@TypeTree() =>
489+
case rhs @ SyntheticBounds() =>
490+
printTypeOrBound(rhs.tpe)
491+
case rhs @ TypeTree() =>
490492
this += " = "
491-
printTypeTree(tpt)
493+
printTypeTree(rhs)
492494
}
493495
}
494496

@@ -606,13 +608,19 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
606608
printTypeTree(lo)
607609
this += " <: "
608610
printTypeTree(hi)
611+
case tpt @ SyntheticBounds() =>
612+
printTypeOrBound(tpt.tpe)
609613
case tpt @ TypeTree() =>
610614
printTypeTree(tpt)
611615
}
612616

613617
def printTypeTree(tree: TypeTree): Buffer = tree match {
614618
case TypeTree.Synthetic() =>
615619
printType(tree.tpe)
620+
tree.tpe match {
621+
case tpe @ Type.TypeRef(name, _) if name.endsWith("$") => this += ".type"
622+
case tpe => this
623+
}
616624

617625
case TypeTree.TypeIdent(name) =>
618626
printType(tree.tpe)
@@ -711,9 +719,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
711719
case Type.TypeRef(name, prefix) =>
712720
prefix match {
713721
case NoPrefix() | Type.ThisType(Types.EmptyPackage()) =>
714-
case prefix@Type() =>
715-
printType(prefix)
716-
this += "."
722+
case prefix@Type() => printType(prefix) += "."
717723
}
718724
this += name.stripSuffix("$")
719725

tests/pos/i2104b.decompiled

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/** Decompiled from out/posTestFromTasty/pos/i2104b/Cons.class */
2+
class Cons[H, T]() extends java.lang.Object
3+
object Cons {
4+
def apply[H, T](h: H, t: T): Cons[H, T] = scala.Predef.???
5+
def unapply[H, T](t: Cons[H, T]): scala.Option[Pair[H, T]] = scala.Predef.???
6+
}
7+
/** Decompiled from out/posTestFromTasty/pos/i2104b/Pair.class */
8+
case class Pair[A, B](_1: A, _2: B) {
9+
override def hashCode(): scala.Int = {
10+
var acc: scala.Int = 2479866
11+
acc = scala.runtime.Statics.mix(acc, scala.runtime.Statics.anyHash(Pair.this._1))
12+
acc = scala.runtime.Statics.mix(acc, scala.runtime.Statics.anyHash(Pair.this._2))
13+
scala.runtime.Statics.finalizeHash(acc, 2)
14+
}
15+
override def equals(x$0: scala.Any): scala.Boolean = this.eq(x$0.asInstanceOf[java.lang.Object]).||(x$0 match {
16+
case x$0: Pair[Pair.this.A, Pair.this.B] =>
17+
this._1.==(x$0._1).&&(this._2.==(x$0._2))
18+
case _ =>
19+
false
20+
})
21+
override def toString(): java.lang.String = scala.runtime.ScalaRunTime._toString(this)
22+
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[Pair[Pair.this.A, Pair.this.B]]
23+
override def productArity: scala.Int = 2
24+
override def productPrefix: java.lang.String = "Pair"
25+
override def productElement(n: scala.Int): scala.Any = n match {
26+
case 0 =>
27+
this._1
28+
case 1 =>
29+
this._2
30+
case _ =>
31+
throw new java.lang.IndexOutOfBoundsException(n.toString())
32+
}
33+
}
34+
object Pair extends scala.AnyRef
35+
/** Decompiled from out/posTestFromTasty/pos/i2104b/Test.class */
36+
object Test {
37+
def main(args: scala.Array[scala.Predef.String]): scala.Unit = {
38+
Cons.apply[scala.Option[scala.Int], scala.None.type](scala.Option.apply[scala.Int](1), scala.None) match {
39+
case Cons(scala.Some(i), scala.None) =>
40+
()
41+
}
42+
}
43+
}

tests/pos/i2104b.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
case class Pair[A, B](_1: A, _2: B)
2+
3+
trait Cons[+H, +T]
4+
5+
object Cons {
6+
def apply[H, T](h: H, t: T): Cons[H, T] = ???
7+
def unapply[H, T](t: Cons[H, T]): Option[Pair[H, T]] = ???
8+
}
9+
10+
object Test {
11+
def main(args: Array[String]): Unit = {
12+
Cons(Option(1), None) match {
13+
case Cons(Some(i), None) =>
14+
}
15+
}
16+
}

tests/pos/tasty/definitions.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,16 @@ object definitions {
102102
case ByName(tpt: TypeTree)
103103
}
104104

105-
/** Trees denoting type bounds*/
105+
/** Trees denoting type bounds */
106106
case class TypeBoundsTree(loBound: TypeTree, hiBound: TypeTree) extends Tree {
107107
def tpe: Type.TypeBounds = ???
108108
}
109109

110+
/** Trees denoting type infered bounds */
111+
case class SyntheticBounds() extends Tree {
112+
def tpe: Type.TypeBounds = ???
113+
}
114+
110115
/** Trees denoting patterns */
111116
enum Pattern extends Positioned {
112117
def tpe: Type = ???

tests/run/tasty-extractors-owners.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ baz2
1717
ValDef("foo2", TypeTree.Synthetic(), None)
1818

1919
<init>
20-
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.Synthetic()), DefDef("b", Nil, Nil, TypeTree.Synthetic(), None), ValDef("b2", TypeTree.Synthetic(), None)))
20+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", SyntheticBounds()), DefDef("b", Nil, Nil, TypeTree.Synthetic(), None), ValDef("b2", TypeTree.Synthetic(), None)))
2121

2222
b
23-
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.Synthetic()), DefDef("b", Nil, Nil, TypeTree.Synthetic(), None), ValDef("b2", TypeTree.Synthetic(), None)))
23+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", SyntheticBounds()), DefDef("b", Nil, Nil, TypeTree.Synthetic(), None), ValDef("b2", TypeTree.Synthetic(), None)))
2424

2525
b2
26-
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.Synthetic()), DefDef("b", Nil, Nil, TypeTree.Synthetic(), None), ValDef("b2", TypeTree.Synthetic(), None)))
26+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", SyntheticBounds()), DefDef("b", Nil, Nil, TypeTree.Synthetic(), None), ValDef("b2", TypeTree.Synthetic(), None)))
2727

0 commit comments

Comments
 (0)