Skip to content

Commit

Permalink
Workaround TreeChecker & specialised tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed May 4, 2022
1 parent ad0c52b commit e6042a5
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 2 deletions.
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,9 @@ class Definitions {

@tu lazy val TupleType: Array[TypeRef | Null] = mkArityArray("scala.Tuple", MaxTupleArity, 1)

def isSpecializedTuple(cls: Symbol): Boolean =
TupleSpecializedClasses.exists(tupleCls => cls.name.isSpecializedNameOf(tupleCls.name))

def SpecialisedTuple(base: Symbol, args: List[Type]): Symbol = base.owner.requiredClass(base.name.specializedName(args))

private class FunType(prefix: String):
Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,16 @@ object NameOps {
classTags.fold(nme.EMPTY)(_ ++ _) ++ nme.specializedTypeNames.suffix)
}

def isSpecializedNameOf(base: N)(using Context): Boolean =
import Decorators.*
val sb = new StringBuilder
sb.append(base.toString)
sb.append(nme.specializedTypeNames.prefix.toString)
sb.append(nme.specializedTypeNames.separator)
val prefix = sb.toString()
val suffix = nme.specializedTypeNames.suffix.toString
name.startsWith(prefix) && name.endsWith(suffix)

def specializedName(args: List[Type])(using Context): N =
val sb = new StringBuilder
sb.append(name.toString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ class SpecializeTuples extends MiniPhase:
override def transformApply(tree: Apply)(using Context): Tree = tree match
case Apply(TypeApply(fun: NameTree, targs), args)
if fun.name == nme.apply && fun.symbol.exists && defn.isSpecializableTuple(fun.symbol.owner.companionClass, targs.map(_.tpe)) =>
Apply(Select(New(defn.SpecialisedTuple(fun.symbol.owner.companionClass, targs.map(_.tpe)).typeRef), nme.CONSTRUCTOR), args)
Apply(Select(New(defn.SpecialisedTuple(fun.symbol.owner.companionClass, targs.map(_.tpe)).typeRef), nme.CONSTRUCTOR), args).withType(tree.tpe)
case Apply(TypeApply(fun: NameTree, targs), args)
if fun.name == nme.CONSTRUCTOR && fun.symbol.exists && defn.isSpecializableTuple(fun.symbol.owner, targs.map(_.tpe)) =>
Apply(Select(New(defn.SpecialisedTuple(fun.symbol.owner, targs.map(_.tpe)).typeRef), nme.CONSTRUCTOR), args)
Apply(Select(New(defn.SpecialisedTuple(fun.symbol.owner, targs.map(_.tpe)).typeRef), nme.CONSTRUCTOR), args).withType(tree.tpe)
case _ => tree
end transformApply

Expand Down
7 changes: 7 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,13 @@ class TreeChecker extends Phase with SymTransformer {
assert(tree.qual.typeOpt.isInstanceOf[ThisType], i"expect prefix of Super to be This, actual = ${tree.qual}")
super.typedSuper(tree, pt)

override def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = tree match
case Apply(Select(qual, nme.CONSTRUCTOR), _)
if !ctx.phase.erasedTypes
&& defn.isSpecializedTuple(qual.typeOpt.typeSymbol) =>
promote(tree) // e.g. `new Tuple2$mcII$sp(7, 8)` should keep its `(7, 8)` type instead of `Tuple2$mcII$sp`
case _ => super.typedApply(tree, pt)

override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree =
val tpt1 = checkSimpleKinded(typedType(tree.tpt))
val expr1 = tree.expr match
Expand Down

0 comments on commit e6042a5

Please sign in to comment.