Skip to content
Closed
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ class Compiler {
new CrossCastAnd, // Normalize selections involving intersection types.
new Splitter), // Expand selections involving union types into conditionals
List(new VCInlineMethods, // Inlines calls to value class methods
new IsInstanceOfEvaluator, // Issues warnings when unreachable statements are present in match/if expressions
new SeqLiterals, // Express vararg arguments as arrays
new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods
new Getters, // Replace non-private vals and vars with getter defs (fields are added later)
Expand Down
20 changes: 20 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,26 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
case _ =>
false
}

/** Structural tree comparison (since == on trees is reference equality).
* For the moment, only Ident, Select, Literal, Apply and TypeApply are supported
*/
implicit class StructuralEqDeco(t1: Tree) {
def === (t2: Tree)(implicit ctx: Context): Boolean = (t1, t2) match {
case (t1: Ident, t2: Ident) =>
t1.symbol == t2.symbol
case (t1 @ Select(q1, _), t2 @ Select(q2, _)) =>
t1.symbol == t2.symbol && q1 === q2
case (Literal(c1), Literal(c2)) =>
c1 == c2
case (Apply(f1, as1), Apply(f2, as2)) =>
f1 === f2 && as1.corresponds(as2)(_ === _)
case (TypeApply(f1, ts1), TypeApply(f2, ts2)) =>
f1 === f2 && ts1.tpes.corresponds(ts2.tpes)(_ =:= _)
case _ =>
false
}
}
}

object TreeInfo {
Expand Down
39 changes: 34 additions & 5 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Denotations._, Decorators._, DenotTransformers._
import collection.mutable
import util.{Property, SourceFile, NoSource}
import typer.ErrorReporting._
import NameKinds.TempResultName
import NameKinds.{TempResultName, OuterSelectName}

import scala.annotation.tailrec
import scala.io.Codec
Expand Down Expand Up @@ -601,7 +601,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply =
ta.assignType(untpd.cpy.TypeApply(tree)(fun, args), fun, args)
// Same remark as for Apply

override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure =
ta.assignType(untpd.cpy.Closure(tree)(env, meth, tpt), meth, tpt)

Expand Down Expand Up @@ -682,6 +682,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def select(name: Name)(implicit ctx: Context): Select =
Select(tree, name)

/** A select node with the given selector name such that the designated
* member satisfies predicate `p`. Useful for disambiguating overloaded members.
*/
def select(name: Name, p: Symbol => Boolean)(implicit ctx: Context): Select =
select(tree.tpe.member(name).suchThat(p).symbol)

/** A select node with the given type */
def select(tp: NamedType)(implicit ctx: Context): Select =
untpd.Select(tree, tp.name).withType(tp)
Expand Down Expand Up @@ -751,9 +757,20 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def ensureApplied(implicit ctx: Context): Tree =
if (tree.tpe.widen.isParameterless) tree else tree.appliedToNone

/** `tree.isInstanceOf[tp]` */
def isInstance(tp: Type)(implicit ctx: Context): Tree =
tree.select(defn.Any_isInstanceOf).appliedToType(tp)
/** `tree == that` */
def equal(that: Tree)(implicit ctx: Context) =
applyOverloaded(tree, nme.EQ, that :: Nil, Nil, defn.BooleanType)

/** `tree.isInstanceOf[tp]`, with special treatment of singleton types */
def isInstance(tp: Type)(implicit ctx: Context): Tree = tp match {
case tp: SingletonType =>
if (tp.widen.derivesFrom(defn.ObjectClass))
tree.ensureConforms(defn.ObjectType).select(defn.Object_eq).appliedTo(singleton(tp))
else
singleton(tp).equal(tree)
case _ =>
tree.select(defn.Any_isInstanceOf).appliedToType(tp)
}

/** tree.asInstanceOf[`tp`] */
def asInstance(tp: Type)(implicit ctx: Context): Tree = {
Expand All @@ -770,6 +787,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
else if (!ctx.erasedTypes) asInstance(tp)
else Erasure.Boxing.adaptToType(tree, tp)

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

/** If inititializer tree is `_', the default value of its type,
* otherwise the tree itself.
*/
Expand Down Expand Up @@ -800,6 +822,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
else Assign(tree, rhs)

/** A synthetic select with that will be turned into an outer path by ExplicitOuter.
* @param levels How many outer levels to select
* @param tp The type of the destination of the outer path.
*/
def outerSelect(levels: Int, tp: Type)(implicit ctx: Context): Tree =
untpd.Select(tree, OuterSelectName(EmptyTermName, levels)).withType(tp)

// --- Higher order traversal methods -------------------------------

/** Apply `f` to each subtree of this tree */
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ object Printers {
val pickling: Printer = noPrinter
val inlining: Printer = noPrinter
val exhaustivity: Printer = noPrinter
val patmatch: Printer = noPrinter
val simplify: Printer = noPrinter
}
8 changes: 7 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,11 @@ class Definitions {
lazy val Any_getClass = enterMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
lazy val Any_isInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
lazy val Any_asInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, TypeParamRef(_, 0), Final)
lazy val Any_typeTest = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOfPM, _ => BooleanType, Final)
// generated by pattern matcher, eliminated by erasure

def AnyMethods = List(Any_==, Any_!=, Any_equals, Any_hashCode,
Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf)
Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf, Any_typeTest)

lazy val ObjectClass: ClassSymbol = {
val cls = ctx.requiredClass("java.lang.Object")
Expand Down Expand Up @@ -371,6 +373,10 @@ class Definitions {
def Seq_apply(implicit ctx: Context) = Seq_applyR.symbol
lazy val Seq_headR = SeqClass.requiredMethodRef(nme.head)
def Seq_head(implicit ctx: Context) = Seq_headR.symbol
lazy val Seq_dropR = SeqClass.requiredMethodRef(nme.drop)
def Seq_drop(implicit ctx: Context) = Seq_dropR.symbol
lazy val Seq_lengthCompareR = SeqClass.requiredMethodRef(nme.lengthCompare)
def Seq_lengthCompare(implicit ctx: Context) = Seq_lengthCompareR.symbol

lazy val ArrayType: TypeRef = ctx.requiredClassRef("scala.Array")
def ArrayClass(implicit ctx: Context) = ArrayType.symbol.asClass
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ object StdNames {
val isDefined: N = "isDefined"
val isEmpty: N = "isEmpty"
val isInstanceOf_ : N = "isInstanceOf"
val isInstanceOfPM: N = "$isInstanceOf$"
val java: N = "java"
val key: N = "key"
val lang: N = "lang"
Expand Down
18 changes: 11 additions & 7 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,16 @@ object Types {
case _ => NoType
}

/** Is this type guaranteed not to have `null` as a value?
* For the moment this is only true for modules, but it could
* be refined later.
*/
final def isNotNull(implicit ctx: Context): Boolean =
classSymbol is ModuleClass
/** Is this type guaranteed not to have `null` as a value? */
final def isNotNull(implicit ctx: Context): Boolean = this match {
case tp: ConstantType => tp.value.value != null
case tp: ClassInfo => !tp.cls.isNullableClass && tp.cls != defn.NothingClass
case tp: TypeBounds => tp.lo.isNotNull
case tp: TypeProxy => tp.underlying.isNotNull
case AndType(tp1, tp2) => tp1.isNotNull || tp2.isNotNull
case OrType(tp1, tp2) => tp1.isNotNull && tp2.isNotNull
case _ => false
}

/** Is this type produced as a repair for an error? */
final def isError(implicit ctx: Context): Boolean = stripTypeVar match {
Expand Down Expand Up @@ -3747,7 +3751,7 @@ object Types {
if (underlying1 eq underlying) tp
else derivedAnnotatedType(tp, underlying1, mapOver(annot))

case tp @ WildcardType =>
case tp: WildcardType =>
derivedWildcardType(tp, mapOver(tp.optBounds))

case tp: JavaArrayType =>
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
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}")
}

object Erasure extends TypeTestsCasts{

object Erasure {
import tpd._
import TypeTestsCasts._

object Boxing {

Expand Down Expand Up @@ -172,7 +172,8 @@ object Erasure extends TypeTestsCasts{
}

def constant(tree: Tree, const: Tree)(implicit ctx: Context) =
if (isPureExpr(tree)) const else Block(tree :: Nil, const)
(if (isPureExpr(tree)) const else Block(tree :: Nil, const))
.withPos(tree.pos)

final def box(tree: Tree, target: => String = "")(implicit ctx: Context): Tree = ctx.traceIndented(i"boxing ${tree.showSummary}: ${tree.tpe} into $target") {
tree.tpe.widen match {
Expand Down
Loading