Skip to content

Commit b989884

Browse files
committed
Merge remote-tracking branch 'origin/add-optimize-patmat' into release-0.2.0
2 parents b8edc55 + e138568 commit b989884

21 files changed

+2967
-1860
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,37 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
663663
case _ =>
664664
false
665665
}
666+
667+
/** Structural tree comparison (since == on trees is reference equality).
668+
* For the moment, only Ident, Select, Literal, Apply and TypeApply are supported
669+
*/
670+
implicit class StructuralEqDeco(t1: Tree) {
671+
def === (t2: Tree)(implicit ctx: Context): Boolean = (t1, t2) match {
672+
case (t1: Ident, t2: Ident) =>
673+
t1.symbol == t2.symbol
674+
case (t1 @ Select(q1, _), t2 @ Select(q2, _)) =>
675+
t1.symbol == t2.symbol && q1 === q2
676+
case (Literal(c1), Literal(c2)) =>
677+
c1 == c2
678+
case (Apply(f1, as1), Apply(f2, as2)) =>
679+
f1 === f2 && as1.corresponds(as2)(_ === _)
680+
case (TypeApply(f1, ts1), TypeApply(f2, ts2)) =>
681+
f1 === f2 && ts1.tpes.corresponds(ts2.tpes)(_ =:= _)
682+
case _ =>
683+
false
684+
}
685+
def hash(implicit ctx: Context): Int =
686+
t1.getClass.hashCode * 37 + {
687+
t1 match {
688+
case t1: Ident => t1.symbol.hashCode
689+
case t1 @ Select(q1, _) => t1.symbol.hashCode * 41 + q1.hash
690+
case Literal(c1) => c1.hashCode
691+
case Apply(f1, as1) => (f1.hash /: as1)((h, arg) => h * 41 + arg.hash)
692+
case TypeApply(f1, ts1) => (f1.hash /: ts1)((h, arg) => h * 41 + arg.tpe.hash)
693+
case _ => t1.hashCode
694+
}
695+
}
696+
}
666697
}
667698

668699
object TreeInfo {

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Denotations._, Decorators._, DenotTransformers._
1212
import collection.mutable
1313
import util.{Property, SourceFile, NoSource}
1414
import typer.ErrorReporting._
15-
import NameKinds.TempResultName
15+
import NameKinds.{TempResultName, OuterSelectName}
1616

1717
import scala.annotation.tailrec
1818
import scala.io.Codec
@@ -171,6 +171,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
171171
def SyntheticValDef(name: TermName, rhs: Tree)(implicit ctx: Context): ValDef =
172172
ValDef(ctx.newSymbol(ctx.owner, name, Synthetic, rhs.tpe.widen, coord = rhs.pos), rhs)
173173

174+
def DefDef(sym: TermSymbol, tparams: List[TypeSymbol], vparamss: List[List[TermSymbol]],
175+
resultType: Type, rhs: Tree)(implicit ctx: Context): DefDef =
176+
ta.assignType(
177+
untpd.DefDef(sym.name, tparams map TypeDef, vparamss.nestedMap(ValDef(_)),
178+
TypeTree(resultType), rhs),
179+
sym)
180+
174181
def DefDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef =
175182
ta.assignType(DefDef(sym, Function.const(rhs) _), sym)
176183

@@ -199,14 +206,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
199206
val (vparamss, rtp) = valueParamss(mtp)
200207
val targs = tparams map (_.typeRef)
201208
val argss = vparamss.nestedMap(vparam => Ident(vparam.termRef))
202-
ta.assignType(
203-
untpd.DefDef(
204-
sym.name,
205-
tparams map TypeDef,
206-
vparamss.nestedMap(ValDef(_)),
207-
TypeTree(rtp),
208-
rhsFn(targs)(argss)),
209-
sym)
209+
DefDef(sym, tparams, vparamss, rtp, rhsFn(targs)(argss))
210210
}
211211

212212
def TypeDef(sym: TypeSymbol)(implicit ctx: Context): TypeDef =
@@ -682,6 +682,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
682682
def select(name: Name)(implicit ctx: Context): Select =
683683
Select(tree, name)
684684

685+
/** A select node with the given selector name such that the designated
686+
* member satisfies predicate `p`. Useful for disambiguating overloaded members.
687+
*/
688+
def select(name: Name, p: Symbol => Boolean)(implicit ctx: Context): Select =
689+
select(tree.tpe.member(name).suchThat(p).symbol)
690+
685691
/** A select node with the given type */
686692
def select(tp: NamedType)(implicit ctx: Context): Select =
687693
untpd.Select(tree, tp.name).withType(tp)
@@ -751,9 +757,20 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
751757
def ensureApplied(implicit ctx: Context): Tree =
752758
if (tree.tpe.widen.isParameterless) tree else tree.appliedToNone
753759

754-
/** `tree.isInstanceOf[tp]` */
755-
def isInstance(tp: Type)(implicit ctx: Context): Tree =
756-
tree.select(defn.Any_isInstanceOf).appliedToType(tp)
760+
/** `tree == that` */
761+
def equal(that: Tree)(implicit ctx: Context) =
762+
applyOverloaded(tree, nme.EQ, that :: Nil, Nil, defn.BooleanType)
763+
764+
/** `tree.isInstanceOf[tp]`, with special treatment of singleton types */
765+
def isInstance(tp: Type)(implicit ctx: Context): Tree = tp match {
766+
case tp: SingletonType =>
767+
if (tp.widen.derivesFrom(defn.ObjectClass))
768+
tree.ensureConforms(defn.ObjectType).select(defn.Object_eq).appliedTo(singleton(tp))
769+
else
770+
singleton(tp).equal(tree)
771+
case _ =>
772+
tree.select(defn.Any_isInstanceOf).appliedToType(tp)
773+
}
757774

758775
/** tree.asInstanceOf[`tp`] */
759776
def asInstance(tp: Type)(implicit ctx: Context): Tree = {
@@ -771,7 +788,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
771788
else Erasure.Boxing.adaptToType(tree, tp)
772789

773790
/** `tree ne null` (might need a cast to be type correct) */
774-
def testNotNull(implicit ctx: Context): Tree =
791+
def testNotNull(implicit ctx: Context): Tree =
775792
tree.ensureConforms(defn.ObjectType)
776793
.select(defn.Object_ne).appliedTo(Literal(Constant(null)))
777794

@@ -805,6 +822,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
805822
}
806823
else Assign(tree, rhs)
807824

825+
/** A synthetic select with that will be turned into an outer path by ExplicitOuter.
826+
* @param levels How many outer levels to select
827+
* @param tp The type of the destination of the outer path.
828+
*/
829+
def outerSelect(levels: Int, tp: Type)(implicit ctx: Context): Tree =
830+
untpd.Select(tree, OuterSelectName(EmptyTermName, levels)).withType(tp)
831+
808832
// --- Higher order traversal methods -------------------------------
809833

810834
/** Apply `f` to each subtree of this tree */

compiler/src/dotty/tools/dotc/config/Printers.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ object Printers {
3232
val pickling: Printer = noPrinter
3333
val inlining: Printer = noPrinter
3434
val exhaustivity: Printer = noPrinter
35+
val patmatch: Printer = noPrinter
3536
val simplify: Printer = noPrinter
3637
}

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class Definitions {
255255
// generated by pattern matcher, eliminated by erasure
256256

257257
def AnyMethods = List(Any_==, Any_!=, Any_equals, Any_hashCode,
258-
Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf)
258+
Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf, Any_typeTest)
259259

260260
lazy val ObjectClass: ClassSymbol = {
261261
val cls = ctx.requiredClass("java.lang.Object")
@@ -373,6 +373,10 @@ class Definitions {
373373
def Seq_apply(implicit ctx: Context) = Seq_applyR.symbol
374374
lazy val Seq_headR = SeqClass.requiredMethodRef(nme.head)
375375
def Seq_head(implicit ctx: Context) = Seq_headR.symbol
376+
lazy val Seq_dropR = SeqClass.requiredMethodRef(nme.drop)
377+
def Seq_drop(implicit ctx: Context) = Seq_dropR.symbol
378+
lazy val Seq_lengthCompareR = SeqClass.requiredMethodRef(nme.lengthCompare)
379+
def Seq_lengthCompare(implicit ctx: Context) = Seq_lengthCompareR.symbol
376380

377381
lazy val ArrayType: TypeRef = ctx.requiredClassRef("scala.Array")
378382
def ArrayClass(implicit ctx: Context) = ArrayType.symbol.asClass

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,7 @@ object Types {
214214
case _ => NoType
215215
}
216216

217-
/** Is this type guaranteed not to have `null` as a value?
218-
* For the moment this is only true for modules, but it could
219-
* be refined later.
220-
*/
217+
/** Is this type guaranteed not to have `null` as a value? */
221218
final def isNotNull(implicit ctx: Context): Boolean = this match {
222219
case tp: ConstantType => tp.value.value != null
223220
case tp: ClassInfo => !tp.cls.isNullableClass && tp.cls != defn.NothingClass
@@ -3753,7 +3750,7 @@ object Types {
37533750
if (underlying1 eq underlying) tp
37543751
else derivedAnnotatedType(tp, underlying1, mapOver(annot))
37553752

3756-
case tp @ WildcardType =>
3753+
case tp: WildcardType =>
37573754
derivedWildcardType(tp, mapOver(tp.optBounds))
37583755

37593756
case tp: JavaArrayType =>

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
139139
i"The type $tp - ${tp.toString} of class ${tp.getClass} of tree $tree : ${tree.tpe} / ${tree.getClass} is illegal after erasure, phase = ${ctx.phase.prev}")
140140
}
141141

142-
object Erasure extends TypeTestsCasts{
143-
142+
object Erasure {
144143
import tpd._
144+
import TypeTestsCasts._
145145

146146
object Boxing {
147147

0 commit comments

Comments
 (0)