aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/transform
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform')
-rw-r--r--compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/transform/CapturedVars.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimByName.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Erasure.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FirstTransform.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/LambdaLift.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/transform/LazyVals.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/transform/LiftTry.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Mixin.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/MoveStatics.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala28
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PostTyper.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/transform/SymUtils.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TailRec.scala37
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TreeChecker.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ValueClasses.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/transform/patmat/Space.scala161
27 files changed, 199 insertions, 197 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
index 9c01aaa9a..f2ffaff5d 100644
--- a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
+++ b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
@@ -14,6 +14,7 @@ import DenotTransformers._
import Annotations._
import StdNames._
import NameOps._
+import NameKinds.{ExpandedName, TraitSetterName}
import ast.Trees._
/** This phase augments Scala2 traits with implementation classes and with additional members
@@ -66,16 +67,16 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform
meth.copy(
owner = implClass,
name = mold.name.asTermName,
- flags = Method | JavaStatic | mold.flags & ExpandedName,
+ flags = Method | JavaStatic,
info = fullyParameterizedType(mold.info, mixin))
}
def traitSetter(getter: TermSymbol) =
getter.copy(
name = getter.ensureNotPrivate.name
- .expandedName(getter.owner, nme.TRAIT_SETTER_SEPARATOR)
+ .expandedName(getter.owner, TraitSetterName)
.asTermName.setterName,
- flags = Method | Accessor | ExpandedName,
+ flags = Method | Accessor,
info = MethodType(getter.info.resultType :: Nil, defn.UnitType))
for (sym <- mixin.info.decls) {
@@ -89,9 +90,9 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform
else if (!sym.is(Deferred) && !sym.setter.exists &&
!sym.info.resultType.isInstanceOf[ConstantType])
traitSetter(sym.asTerm).enteredAfter(thisTransform)
- if ((sym.is(PrivateAccessor, butNot = ExpandedName) &&
+ if ((sym.is(PrivateAccessor) && !sym.name.is(ExpandedName) &&
(sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set.
- || sym.is(SuperAccessor)) // scala2 superaccessors are pickled as private, but are compiled as public expanded
+ || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded
sym.ensureNotPrivate.installAfter(thisTransform)
}
ctx.log(i"Scala2x trait decls of $mixin = ${mixin.info.decls.toList.map(_.showDcl)}%\n %")
diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala
index cd05589c3..b9a9544f5 100644
--- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala
+++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala
@@ -12,6 +12,7 @@ import core.SymDenotations._
import core.StdNames.nme
import core.Names._
import core.NameOps._
+import core.NameKinds.TempResultName
import ast.Trees._
import SymUtils._
import collection.{ mutable, immutable }
@@ -138,7 +139,7 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransfo
val Select(_, nme.elem) = qual
recur(qual)
case Select(_, nme.elem) if refInfo.boxedRefClasses.contains(lhs.symbol.maybeOwner) =>
- val tempDef = transformFollowing(SyntheticValDef(ctx.freshName("ev$").toTermName, tree.rhs))
+ val tempDef = transformFollowing(SyntheticValDef(TempResultName.fresh(), tree.rhs))
transformFollowing(Block(tempDef :: Nil, cpy.Assign(tree)(lhs, ref(tempDef.symbol))))
case _ =>
tree
diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
index 839552799..06c489029 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
@@ -112,6 +112,9 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree =
applyIfFunction(tree, tree)
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
+ applyIfFunction(tree, tree)
+
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = tree match {
case TypeApply(Select(_, nme.asInstanceOf_), arg :: Nil) =>
// tree might be of form e.asInstanceOf[x.type] where x becomes a function.
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
index d64120085..4cee0d0de 100644
--- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
@@ -11,6 +11,7 @@ import core.Types._
import core.Names._
import core.StdNames._
import core.NameOps._
+import core.NameKinds.ShadowedName
import core.Decorators._
import core.Constants._
import core.Definitions._
@@ -363,7 +364,7 @@ object Erasure extends TypeTestsCasts{
def select(qual: Tree, sym: Symbol): Tree = {
val name = tree.typeOpt match {
- case tp: NamedType if tp.name.isShadowedName => sym.name.shadowedName
+ case tp: NamedType if tp.name.is(ShadowedName) => sym.name.derived(ShadowedName)
case _ => sym.name
}
untpd.cpy.Select(tree)(qual, sym.name)
diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
index 7b15b7e54..f63cba3f1 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
@@ -38,7 +38,7 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer =>
case tpe @ SAMType(_) if isPlatformSam(tpe.classSymbol.asClass) =>
tree
case tpe =>
- val Seq(samDenot) = tpe.abstractTermMembers.filter(!_.symbol.is(SuperAccessor))
+ val Seq(samDenot) = tpe.abstractTermMembers.filter(!_.symbol.isSuperAccessor)
cpy.Block(tree)(stats,
AnonClass(tpe :: Nil, fn.symbol.asTerm :: Nil, samDenot.symbol.asTerm.name :: Nil))
}
diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index a6e643992..7ad7fb348 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -11,6 +11,7 @@ import core.Decorators._
import core.StdNames.nme
import core.Names._
import core.NameOps._
+import core.NameKinds.OuterSelectName
import ast.Trees._
import SymUtils._
import dotty.tools.dotc.ast.tpd
@@ -61,10 +62,11 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf
/** Convert a selection of the form `qual.C_<OUTER>` to an outer path from `qual` to `C` */
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
- if (tree.name.isOuterSelect)
- outer.path(start = tree.qualifier, count = tree.name.outerSelectHops)
- .ensureConforms(tree.tpe)
- else tree
+ tree.name match {
+ case OuterSelectName(_, nhops) =>
+ outer.path(start = tree.qualifier, count = nhops).ensureConforms(tree.tpe)
+ case _ => tree
+ }
/** First, add outer accessors if a class does not have them yet and it references an outer this.
* If the class has outer accessors, implement them.
@@ -215,7 +217,7 @@ object ExplicitOuter {
def outerAccessor(cls: ClassSymbol)(implicit ctx: Context): Symbol =
if (cls.isStatic) NoSymbol // fast return to avoid scanning package decls
else cls.info.member(outerAccName(cls)).suchThat(_ is OuterAccessor).symbol orElse
- cls.info.decls.find(_ is OuterAccessor).getOrElse(NoSymbol)
+ cls.info.decls.find(_ is OuterAccessor)
/** Class has an outer accessor. Can be called only after phase ExplicitOuter. */
private def hasOuter(cls: ClassSymbol)(implicit ctx: Context): Boolean =
diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala
index 64474cecd..61f32edae 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala
@@ -16,6 +16,7 @@ import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTrans
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
import TypeErasure.{ valueErasure, ErasedValueType }
import TypeUtils._
+import NameKinds.{ExtMethName, UniqueExtMethName}
import util.Positions._
import Decorators._
import SymUtils._
@@ -206,11 +207,11 @@ object ExtensionMethods {
val alts = decl.alternatives
val index = alts indexOf imeth.denot
assert(index >= 0, alts + " does not contain " + imeth)
- def altName(index: Int) = (imeth.name + "$extension" + index).toTermName
+ def altName(index: Int) = UniqueExtMethName(imeth.name.asTermName, index)
altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName)
case decl =>
assert(decl.exists, imeth.name + " not found in " + imeth.owner + "'s decls: " + imeth.owner.info.decls)
- Stream((imeth.name + "$extension").toTermName)
+ Stream(ExtMethName(imeth.name.asTermName))
}
}
diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
index 8328e43de..a3cf71ef2 100644
--- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -19,8 +19,8 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation
import scala.collection.mutable
import DenotTransformers._
import typer.Checking
-import Names.Name
import NameOps._
+import NameKinds.{AvoidClashName, OuterSelectName}
import StdNames._
@@ -77,7 +77,7 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
tree match {
- case Select(qual, name) if !name.isOuterSelect && tree.symbol.exists =>
+ case Select(qual, name) if !name.is(OuterSelectName) && tree.symbol.exists =>
assert(qual.tpe derivesFrom tree.symbol.owner, i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe} in $tree")
case _: TypeTree =>
case _: Import | _: NamedArg | _: TypTree =>
@@ -129,7 +129,7 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
case _ =>
false
}
- val uniqueName = if (nameClash) objName.avoidClashName else objName
+ val uniqueName = if (nameClash) AvoidClashName(objName) else objName
Thicket(stat :: ModuleDef(registerCompanion(uniqueName, stat.symbol), Nil).trees)
case stat => stat
}
diff --git a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
index ebd2ae436..b48d219d6 100644
--- a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
+++ b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
@@ -147,6 +147,9 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
(scTrait && selTrait)
val inMatch = s.qualifier.symbol is Case
+ // FIXME: This will misclassify case objects! We need to find another way to characterize
+ // isInstanceOfs generated by matches.
+ // Probably the most robust way is to use another symbol for the isInstanceOf method.
if (valueClassesOrAny) tree
else if (knownStatically)
diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
index 7578b57f1..a729368d4 100644
--- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
+++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
@@ -143,13 +143,17 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
/** Set `liftedOwner(sym)` to `owner` if `owner` is more deeply nested
* than the previous value of `liftedowner(sym)`.
*/
- def narrowLiftedOwner(sym: Symbol, owner: Symbol)(implicit ctx: Context) =
+ def narrowLiftedOwner(sym: Symbol, owner: Symbol)(implicit ctx: Context): Unit =
if (sym.maybeOwner.isTerm &&
owner.isProperlyContainedIn(liftedOwner(sym)) &&
owner != sym) {
- ctx.log(i"narrow lifted $sym to $owner")
- changedLiftedOwner = true
- liftedOwner(sym) = owner
+ if (sym.is(InSuperCall) && owner.isProperlyContainedIn(sym.enclosingClass))
+ narrowLiftedOwner(sym, sym.enclosingClass)
+ else {
+ ctx.log(i"narrow lifted $sym to $owner")
+ changedLiftedOwner = true
+ liftedOwner(sym) = owner
+ }
}
/** Mark symbol `sym` as being free in `enclosure`, unless `sym` is defined
diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
index 2035fb04b..f64006d73 100644
--- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -10,6 +10,7 @@ import Contexts._
import Symbols._
import Decorators._
import NameOps._
+import NameKinds._
import StdNames.nme
import rewrite.Rewrites.patch
import util.Positions.Position
@@ -106,7 +107,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
*/
def transformSyntheticModule(tree: ValOrDefDef)(implicit ctx: Context) = {
val sym = tree.symbol
- val holderSymbol = ctx.newSymbol(sym.owner, sym.asTerm.name.lazyLocalName,
+ val holderSymbol = ctx.newSymbol(sym.owner, LazyLocalName.fresh(sym.asTerm.name),
Flags.Synthetic, sym.info.widen.resultType).enteredAfter(this)
val field = ValDef(holderSymbol, tree.rhs.changeOwnerAfter(sym, holderSymbol, this))
val getter = DefDef(sym.asTerm, ref(holderSymbol))
@@ -119,8 +120,9 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
*/
def transformLocalDef(x: ValOrDefDef)(implicit ctx: Context) = {
val valueInitter = x.rhs
- val holderName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName
- val initName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL_INIT).toTermName
+ val xname = x.name.asTermName
+ val holderName = LazyLocalName.fresh(xname)
+ val initName = LazyLocalInitName.fresh(xname)
val tpe = x.tpe.widen.resultType.widen
val holderType =
@@ -211,7 +213,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
val claz = x.symbol.owner.asClass
val tpe = x.tpe.widen.resultType.widen
assert(!(x.symbol is Flags.Mutable))
- val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName
+ val containerName = LazyLocalName.fresh(x.name.asTermName)
val containerSymbol = ctx.newSymbol(claz, containerName,
x.symbol.flags &~ containerFlagsMask | containerFlags | Flags.Private,
tpe, coord = x.symbol.coord
@@ -223,7 +225,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
Thicket(containerTree, slowPath)
}
else {
- val flagName = ctx.freshName(x.name ++ StdNames.nme.BITMAP_PREFIX).toTermName
+ val flagName = LazyBitMapName.fresh(x.name.asTermName)
val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags | Flags.Private, defn.BooleanType).enteredAfter(this)
val flag = ValDef(flagSymbol, Literal(Constants.Constant(false)))
val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(ref(containerSymbol), ref(flagSymbol), x.rhs))
@@ -376,7 +378,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
appendOffsetDefs += (claz -> new OffsetInfo(List(offsetTree), ord))
}
- val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName
+ val containerName = LazyLocalName.fresh(x.name.asTermName)
val containerSymbol = ctx.newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags, tpe, coord = x.symbol.coord).enteredAfter(this)
val containerTree = ValDef(containerSymbol, defaultValue(tpe))
diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala
index d01195614..278868131 100644
--- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala
+++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala
@@ -8,6 +8,7 @@ import core.Contexts._
import core.Types._
import core.Flags._
import core.Decorators._
+import core.NameKinds.LiftedTreeName
import NonLocalReturns._
/** Lifts try's that might be executed on non-empty expression stacks
@@ -56,7 +57,7 @@ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisTransform =>
if (needLift) {
ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}")
val fn = ctx.newSymbol(
- ctx.owner, ctx.freshName("liftedTree").toTermName, Synthetic | Method,
+ ctx.owner, LiftedTreeName.fresh(), Synthetic | Method,
MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.pos)
tree.changeOwnerAfter(ctx.owner, fn, thisTransform)
Block(DefDef(fn, tree) :: Nil, ref(fn).appliedToNone)
diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
index fd4370d3e..546077d27 100644
--- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
@@ -13,6 +13,7 @@ import Decorators._
import DenotTransformers._
import StdNames._
import NameOps._
+import NameKinds._
import Phases._
import ast.untpd
import ast.Trees._
@@ -219,7 +220,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
ref(mixin.implClass).select(implClassGetter).appliedTo(This(cls))
}
- if (isCurrent(getter) || getter.is(ExpandedName)) {
+ if (isCurrent(getter) || getter.name.is(ExpandedName)) {
val rhs =
if (was(getter, ParamAccessor)) nextArgument()
else if (isScala2x)
diff --git a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala
index b0ee0930d..652320639 100644
--- a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala
+++ b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala
@@ -55,6 +55,7 @@ class MoveStatics extends MiniPhaseTransform with SymTransformer { thisTransform
}
def move(module: TypeDef, companion: TypeDef): List[Tree] = {
+ assert(companion ne module)
if (!module.symbol.is(Flags.Module)) move(companion, module)
else {
val allMembers =
diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala
index 7680e283e..fdee076b4 100644
--- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala
+++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala
@@ -5,6 +5,7 @@ import core._
import Contexts._, Symbols._, Types._, Flags._, Decorators._, StdNames._, Constants._, Phases._
import TreeTransforms._
import ast.Trees._
+import NameKinds.NonLocalReturnKeyName
import collection.mutable
object NonLocalReturns {
@@ -38,7 +39,7 @@ class NonLocalReturns extends MiniPhaseTransform { thisTransformer =>
private def nonLocalReturnKey(meth: Symbol)(implicit ctx: Context) =
nonLocalReturnKeys.getOrElseUpdate(meth,
ctx.newSymbol(
- meth, ctx.freshName("nonLocalReturnKey").toTermName, Synthetic, defn.ObjectType, coord = meth.pos))
+ meth, NonLocalReturnKeyName.fresh(), Synthetic, defn.ObjectType, coord = meth.pos))
/** Generate a non-local return throw with given return expression from given method.
* I.e. for the method's non-local return key, generate:
diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
index dbc7666f7..41a1218eb 100644
--- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -11,6 +11,7 @@ import core.Symbols._
import core.Types._
import core.Constants._
import core.StdNames._
+import core.NameKinds._
import dotty.tools.dotc.ast.{untpd, TreeTypeMap, tpd}
import dotty.tools.dotc.core
import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
@@ -70,16 +71,14 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
class OptimizingMatchTranslator extends MatchOptimizer/*(val typer: analyzer.Typer)*/ with MatchTranslator
trait CodegenCore {
- private var ctr = 0 // left for debugging
// assert(owner ne null); assert(owner ne NoSymbol)
- def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x", owner: Symbol = ctx.owner) = {
- ctr += 1
- ctx.newSymbol(owner, ctx.freshName(prefix + ctr).toTermName, Flags.Synthetic | Flags.Case, tp, coord = pos)
+ def freshSym(pos: Position, tp: Type = NoType, unique: UniqueNameKind = PatMatStdBinderName, owner: Symbol = ctx.owner) = {
+ ctx.newSymbol(owner, unique.fresh(), Flags.Synthetic | Flags.Case, tp, coord = pos)
}
- def newSynthCaseLabel(name: String, tpe: Type, owner: Symbol = ctx.owner) =
- ctx.newSymbol(owner, ctx.freshName(name).toTermName, Flags.Label | Flags.Synthetic | Flags.Method, tpe).asTerm
+ def newSynthCaseLabel(unique: UniqueNameKind, tpe: Type, owner: Symbol = ctx.owner) =
+ ctx.newSymbol(owner, unique.fresh(), Flags.Label | Flags.Synthetic | Flags.Method, tpe).asTerm
//NoSymbol.newLabel(freshName(name), NoPosition) setFlag treeInfo.SYNTH_CASE_FLAGS
// codegen relevant to the structure of the translation (how extractors are combined)
@@ -189,7 +188,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
//NoSymbol.newValueParameter(newTermName("x"), NoPosition, newFlags = SYNTHETIC) setInfo restpe.withoutAnnotations
- val caseSyms: List[TermSymbol] = cases.scanLeft(ctx.owner.asTerm)((curOwner, nextTree) => newSynthCaseLabel(ctx.freshName("case"), MethodType(Nil, restpe), curOwner)).tail
+ val caseSyms: List[TermSymbol] = cases.scanLeft(ctx.owner.asTerm)((curOwner, nextTree) =>
+ newSynthCaseLabel(PatMatCaseName, MethodType(Nil, restpe), curOwner)).tail
// must compute catchAll after caseLabels (side-effects nextCase)
// catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default)
@@ -197,7 +197,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
val catchAllDef = matchFailGen.map { _(scrutSym) }
.getOrElse(Throw(New(defn.MatchErrorType, List(ref(scrutSym)))))
- val matchFail = newSynthCaseLabel(ctx.freshName("matchFail"), MethodType(Nil, restpe))
+ val matchFail = newSynthCaseLabel(PatMatMatchFailName, MethodType(Nil, restpe))
val catchAllDefBody = DefDef(matchFail, catchAllDef)
val nextCases = (caseSyms.tail ::: List(matchFail)).map(ref(_).ensureApplied)
@@ -233,7 +233,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
// next: MatchMonad[U]
// returns MatchMonad[U]
def flatMap(prev: Tree, b: Symbol, next: Tree): Tree = {
- val resultArity = defn.productArity(b.info)
+ val resultArity = productArity(b.info)
if (isProductMatch(prev.tpe, resultArity)) {
val nullCheck: Tree = prev.select(defn.Object_ne).appliedTo(Literal(Constant(null)))
ifThenElseZero(
@@ -249,7 +249,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
val isEmptyDenot = extractorMember(prev.tpe, nme.isEmpty)
assert(getDenot.exists && isEmptyDenot.exists, i"${prev.tpe}")
- val tmpSym = freshSym(prev.pos, prev.tpe, "o")
+ val tmpSym = freshSym(prev.pos, prev.tpe, PatMatOName)
val prevValue = ref(tmpSym).select(getDenot.symbol).ensureApplied
Block(
@@ -1056,9 +1056,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
}
def newBoundTree(tree: Tree, pt: Type): BoundTree = tree match {
- case SymbolBound(sym, Typed(subpat, tpe)) => BoundTree(freshSym(tree.pos, pt, prefix = "pi"), tree)
+ case SymbolBound(sym, Typed(subpat, tpe)) => BoundTree(freshSym(tree.pos, pt, PatMatPiName), tree)
case SymbolBound(sym, expr) => BoundTree(sym, expr)
- case _ => BoundTree(freshSym(tree.pos, pt, prefix = "p"), tree)
+ case _ => BoundTree(freshSym(tree.pos, pt, PatMatPName), tree)
}
final case class BoundTree(binder: Symbol, tree: Tree) {
@@ -1204,7 +1204,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
val selectorTp = sel.tpe.widen.deAnonymize/*withoutAnnotations*/
- val selectorSym = freshSym(sel.pos, selectorTp, "selector")
+ val selectorSym = freshSym(sel.pos, selectorTp, PatMatSelectorName)
val (nonSyntheticCases, defaultOverride) = cases match {
case init :+ last if isSyntheticDefaultCase(last) => (init, Some(((scrut: Symbol) => last.body)))
@@ -1408,7 +1408,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
protected def seqTree(binder: Symbol) = tupleSel(binder)(firstIndexingBinder + 1)
protected def tupleSel(binder: Symbol)(i: Int): Tree = {
val accessors =
- if (defn.isProductSubType(binder.info))
+ if (Applications.canProductMatch(binder.info))
productSelectors(binder.info)
else binder.caseAccessors
val res =
diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
index 9821757e8..bacb88091 100644
--- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -104,8 +104,14 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
private def transformAnnot(annot: Annotation)(implicit ctx: Context): Annotation =
annot.derivedAnnotation(transformAnnot(annot.tree))
+ private def registerChild(sym: Symbol, tp: Type)(implicit ctx: Context) = {
+ val cls = tp.classSymbol
+ if (cls.is(Sealed)) cls.addAnnotation(Annotation.makeChild(sym))
+ }
+
private def transformMemberDef(tree: MemberDef)(implicit ctx: Context): Unit = {
val sym = tree.symbol
+ if (sym.is(CaseVal, butNot = Method | Module)) registerChild(sym, sym.info)
sym.transformAnnotations(transformAnnot)
}
@@ -227,9 +233,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
// Add Child annotation to sealed parents unless current class is anonymous
if (!sym.isAnonymousClass) // ignore anonymous class
- for (parent <- sym.asClass.classInfo.classParents) {
- val pclazz = parent.classSymbol
- if (pclazz.is(Sealed)) pclazz.addAnnotation(Annotation.makeChild(sym))
+ sym.asClass.classInfo.classParents.foreach { parent =>
+ val sym2 = if (sym.is(Module)) sym.sourceModule else sym
+ registerChild(sym2, parent)
}
tree
diff --git a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala
index d752ce8e7..7c51ba593 100644
--- a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala
@@ -43,7 +43,7 @@ class PrimitiveForwarders extends MiniPhaseTransform with IdentityDenotTransform
import ops._
def methodPrimitiveForwarders: List[Tree] =
- for (meth <- mixins.flatMap(_.info.decls.flatMap(needsPrimitiveForwarderTo)).distinct)
+ for (meth <- mixins.flatMap(_.info.decls.toList.flatMap(needsPrimitiveForwarderTo)).distinct)
yield polyDefDef(implementation(meth.asTerm), forwarder(meth))
cpy.Template(impl)(body = methodPrimitiveForwarders ::: impl.body)
diff --git a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala
index 3a301167d..e7936e8d9 100644
--- a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala
@@ -13,11 +13,13 @@ import Decorators._
import DenotTransformers._
import StdNames._
import NameOps._
+import NameKinds._
import ast.Trees._
import util.Positions._
import Names._
import collection.mutable
import ResolveSuper._
+import config.Config
/** This phase adds super accessors and method overrides where
* linearization differs from Java's rule for default methods in interfaces.
@@ -58,7 +60,7 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
import ops._
def superAccessors(mixin: ClassSymbol): List[Tree] =
- for (superAcc <- mixin.info.decls.filter(_ is SuperAccessor).toList)
+ for (superAcc <- mixin.info.decls.filter(_.isSuperAccessor).toList)
yield polyDefDef(implementation(superAcc.asTerm), forwarder(rebindSuper(cls, superAcc)))
def methodOverrides(mixin: ClassSymbol): List[Tree] =
@@ -72,7 +74,7 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
val meth = ddef.symbol.asTerm
- if (meth.is(SuperAccessor, butNot = Deferred)) {
+ if (meth.isSuperAccessor && !meth.is(Deferred)) {
assert(ddef.rhs.isEmpty)
val cls = meth.owner.asClass
val ops = new MixinOps(cls, thisTransform)
@@ -94,13 +96,7 @@ object ResolveSuper {
def rebindSuper(base: Symbol, acc: Symbol)(implicit ctx: Context): Symbol = {
var bcs = base.info.baseClasses.dropWhile(acc.owner != _).tail
var sym: Symbol = NoSymbol
- val unexpandedAccName =
- if (acc.is(ExpandedName)) // Cannot use unexpandedName because of #765. t2183.scala would fail if we did.
- acc.name
- .drop(acc.name.indexOfSlice(nme.EXPAND_SEPARATOR ++ nme.SUPER_PREFIX))
- .drop(nme.EXPAND_SEPARATOR.length)
- else acc.name
- val SuperAccessorName(memberName) = unexpandedAccName: Name // dotty deviation: ": Name" needed otherwise pattern type is neither a subtype nor a supertype of selector type
+ val SuperAccessorName(memberName) = acc.name.unexpandedName // dotty deviation: ": Name" needed otherwise pattern type is neither a subtype nor a supertype of selector type
ctx.debuglog(i"starting rebindsuper from $base of ${acc.showLocated}: ${acc.info} in $bcs, name = $memberName")
while (bcs.nonEmpty && sym == NoSymbol) {
val other = bcs.head.info.nonPrivateDecl(memberName)
diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala
index 1a530b95c..2fea19847 100644
--- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala
@@ -11,6 +11,7 @@ import core.Decorators._
import core.StdNames.nme
import core.Names._
import core.NameOps._
+import core.NameKinds.DirectName
import ast.Trees._
import ast.tpd
import collection.mutable
@@ -91,7 +92,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
/** A new `m$direct` method to accompany the given method `m` */
private def newDirectMethod(sym: Symbol)(implicit ctx: Context): Symbol = {
val direct = sym.copy(
- name = sym.name.directName,
+ name = DirectName(sym.name.asTermName).asInstanceOf[sym.ThisName],
flags = sym.flags | Synthetic,
info = directInfo(sym.info))
if (direct.allOverriddenSymbols.isEmpty) direct.resetFlag(Override)
@@ -103,7 +104,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
*/
private def directMethod(sym: Symbol)(implicit ctx: Context): Symbol =
if (sym.owner.isClass) {
- val direct = sym.owner.info.member(sym.name.directName)
+ val direct = sym.owner.info.member(DirectName(sym.name.asTermName))
.suchThat(_.info matches directInfo(sym.info)).symbol
if (direct.maybeOwner == sym.owner) direct
else newDirectMethod(sym).enteredAfter(thisTransform)
@@ -121,7 +122,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
case TypeApply(fn, args) => cpy.TypeApply(tree)(directQual(fn), args)
case Block(stats, expr) => cpy.Block(tree)(stats, directQual(expr))
case tree: RefTree =>
- cpy.Ref(tree)(tree.name.directName)
+ cpy.Ref(tree)(DirectName(tree.name.asTermName))
.withType(directMethod(tree.symbol).termRef)
}
directQual(tree.qualifier)
diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala
index 728c1696b..84a32f93b 100644
--- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala
+++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala
@@ -11,6 +11,7 @@ import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTrans
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
import util.Positions._
import Decorators._
+import NameKinds.{ProtectedAccessorName, ProtectedSetterName, OuterSelectName, SuperAccessorName}
import Symbols._, TypeUtils._
/** This class performs the following functions:
@@ -71,7 +72,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
val Select(qual, name) = sel
val sym = sel.symbol
val clazz = qual.symbol.asClass
- var superName = name.superName
+ var superName = SuperAccessorName(name.asTermName)
if (clazz is Trait) superName = superName.expandedName(clazz)
val superInfo = sel.tpe.widenSingleton.ensureMethodic
@@ -79,9 +80,9 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
.suchThat(_.signature == superInfo.signature).symbol
.orElse {
ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz")
- val deferredOrPrivate = if (clazz is Trait) Deferred | ExpandedName else Private
+ val deferredOrPrivate = if (clazz is Trait) Deferred else Private
val acc = ctx.newSymbol(
- clazz, superName, SuperAccessor | Artifact | Method | deferredOrPrivate,
+ clazz, superName, Artifact | Method | deferredOrPrivate,
superInfo, coord = sym.coord).enteredAfter(thisTransformer)
// Diagnostic for SI-7091
if (!accDefs.contains(clazz))
@@ -151,7 +152,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
*/
private def ensureProtectedAccessOK(sel: Select, targs: List[Tree])(implicit ctx: Context) = {
val sym = sel.symbol
- if (sym.isTerm && !sel.name.isOuterSelect && needsProtectedAccessor(sym, sel.pos)) {
+ if (sym.isTerm && !sel.name.is(OuterSelectName) && needsProtectedAccessor(sym, sel.pos)) {
ctx.debuglog("Adding protected accessor for " + sel)
protectedAccessorCall(sel, targs)
} else sel
@@ -168,7 +169,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
assert(clazz.exists, sym)
ctx.debuglog("Decided for host class: " + clazz)
- val accName = sym.name.protectedAccessorName
+ val accName = ProtectedAccessorName(sym.name)
// if the result type depends on the this type of an enclosing class, the accessor
// has to take an object of exactly this type, otherwise it's more general
@@ -206,7 +207,8 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
}
def isProtectedAccessor(tree: Tree)(implicit ctx: Context): Boolean = tree match {
- case Apply(TypeApply(Select(_, name), _), qual :: Nil) => name.isProtectedAccessorName
+ case Apply(TypeApply(Select(_, name), _), qual :: Nil) =>
+ name.is(ProtectedAccessorName) || name.is(ProtectedSetterName)
case _ => false
}
@@ -221,7 +223,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
assert(clazz.exists, sym)
ctx.debuglog("Decided for host class: " + clazz)
- val accName = sym.name.protectedAccessorName
+ val accName = ProtectedAccessorName(sym.name)
// if the result type depends on the this type of an enclosing class, the accessor
// has to take an object of exactly this type, otherwise it's more general
@@ -265,7 +267,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
assert(clazz.exists, field)
ctx.debuglog("Decided for host class: " + clazz)
- val accName = field.name.protectedSetterName
+ val accName = ProtectedSetterName(field.name)
val accType = MethodType(clazz.classInfo.selfType :: field.info :: Nil, defn.UnitType)
val protectedAccessor = clazz.info.decl(accName).symbol orElse {
val newAcc = ctx.newSymbol(
diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala
index 105f54d3a..4c07ca4c8 100644
--- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala
+++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala
@@ -10,6 +10,7 @@ import Decorators._
import Names._
import StdNames._
import NameOps._
+import NameKinds._
import Flags._
import Annotations._
@@ -51,6 +52,11 @@ class SymUtils(val self: Symbol) extends AnyVal {
def isAnyOverride(implicit ctx: Context) = self.is(Override) || self.is(AbsOverride)
// careful: AbsOverride is a term only flag. combining with Override would catch only terms.
+ def isAliasPreferred(implicit ctx: Context) =
+ self.is(AliasPreferred) || self.name.is(ExpandedName)
+
+ def isSuperAccessor(implicit ctx: Context) = self.name.is(SuperAccessorName)
+
/** If this is a constructor, its owner: otherwise this. */
final def skipConstructor(implicit ctx: Context): Symbol =
if (self.isConstructor) self.owner else self
diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala
index 8a695bf22..10c18e165 100644
--- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala
+++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala
@@ -1,16 +1,17 @@
-package dotty.tools.dotc.transform
-
-import dotty.tools.dotc.ast.Trees._
-import dotty.tools.dotc.ast.{TreeTypeMap, tpd}
-import dotty.tools.dotc.core.Contexts.Context
-import dotty.tools.dotc.core.Decorators._
-import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
-import dotty.tools.dotc.core.Denotations.SingleDenotation
-import dotty.tools.dotc.core.Symbols._
-import dotty.tools.dotc.core.Types._
-import dotty.tools.dotc.core._
-import dotty.tools.dotc.transform.TailRec._
-import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo}
+package dotty.tools.dotc
+package transform
+
+import ast.Trees._
+import ast.{TreeTypeMap, tpd}
+import core._
+import Contexts.Context
+import Decorators._
+import DenotTransformers.DenotTransformer
+import Denotations.SingleDenotation
+import Symbols._
+import Types._
+import NameKinds.TailLabelName
+import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
/**
* A Tail Rec Transformer
@@ -62,6 +63,7 @@ import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, Transforme
* </p>
*/
class TailRec extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransform =>
+ import TailRec._
import dotty.tools.dotc.ast.tpd._
@@ -70,7 +72,6 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
override def phaseName: String = "tailrec"
override def treeTransformPhase = thisTransform // TODO Make sure tailrec runs at next phase.
- final val labelPrefix = "tailLabel"
final val labelFlags = Flags.Synthetic | Flags.Label
/** Symbols of methods that have @tailrec annotatios inside */
@@ -87,12 +88,12 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
tree
}
- private def mkLabel(method: Symbol, abstractOverClass: Boolean)(implicit c: Context): TermSymbol = {
- val name = c.freshName(labelPrefix)
+ private def mkLabel(method: Symbol, abstractOverClass: Boolean)(implicit ctx: Context): TermSymbol = {
+ val name = TailLabelName.fresh()
if (method.owner.isClass)
- c.newSymbol(method, name.toTermName, labelFlags, fullyParameterizedType(method.info, method.enclosingClass.asClass, abstractOverClass, liftThisType = false))
- else c.newSymbol(method, name.toTermName, labelFlags, method.info)
+ ctx.newSymbol(method, name.toTermName, labelFlags, fullyParameterizedType(method.info, method.enclosingClass.asClass, abstractOverClass, liftThisType = false))
+ else ctx.newSymbol(method, name.toTermName, labelFlags, method.info)
}
override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
index ebb5b605b..eb7773ef3 100644
--- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -13,6 +13,7 @@ import core.Flags._
import core.Constants._
import core.StdNames._
import core.NameOps._
+import core.NameKinds.OuterSelectName
import core.Decorators._
import core.TypeErasure.isErasedType
import core.Phases.Phase
@@ -50,10 +51,10 @@ class TreeChecker extends Phase with SymTransformer {
private val seenModuleVals = collection.mutable.HashMap[String, Symbol]()
def isValidJVMName(name: Name) =
- !name.exists(c => c == '.' || c == ';' || c =='[' || c == '/')
+ !name.toString.exists(c => c == '.' || c == ';' || c =='[' || c == '/')
def isValidJVMMethodName(name: Name) =
- !name.exists(c => c == '.' || c == ';' || c =='[' || c == '/' || c == '<' || c == '>')
+ !name.toString.exists(c => c == '.' || c == ';' || c =='[' || c == '/' || c == '<' || c == '>')
def printError(str: String)(implicit ctx: Context) = {
ctx.echo(Console.RED + "[error] " + Console.WHITE + str)
@@ -339,7 +340,7 @@ class TreeChecker extends Phase with SymTransformer {
val sym = tree.symbol
if (!tpe.isInstanceOf[WithFixedSym] &&
sym.exists && !sym.is(Private) &&
- !tree.name.isOuterSelect // outer selects have effectively fixed symbols
+ !tree.name.is(OuterSelectName) // outer selects have effectively fixed symbols
) {
val qualTpe = tree.qualifier.typeOpt
val member =
@@ -390,11 +391,11 @@ class TreeChecker extends Phase with SymTransformer {
!x.isCompanionMethod &&
!x.isValueClassConvertMethod
- val symbolsNotDefined = cls.classInfo.decls.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol
+ val symbolsNotDefined = cls.classInfo.decls.toList.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol
assert(symbolsNotDefined.isEmpty,
i" $cls tree does not define methods: ${symbolsNotDefined.toList}%, %\n" +
- i"expected: ${cls.classInfo.decls.toSet.filter(isNonMagicalMethod).toList}%, %\n" +
+ i"expected: ${cls.classInfo.decls.toList.toSet.filter(isNonMagicalMethod)}%, %\n" +
i"defined: ${impl.body.map(_.symbol)}%, %")
super.typedClassDef(cdef, cls)
@@ -403,7 +404,8 @@ class TreeChecker extends Phase with SymTransformer {
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) =
withDefinedSyms(ddef.tparams) {
withDefinedSymss(ddef.vparamss) {
- if (!sym.isClassConstructor && !(sym.name eq Names.STATIC_CONSTRUCTOR)) assert(isValidJVMMethodName(sym.name), s"${sym.fullName} name is invalid on jvm")
+ if (!sym.isClassConstructor && !(sym.name eq Names.STATIC_CONSTRUCTOR))
+ assert(isValidJVMMethodName(sym.name), s"${sym.name.debugString} name is invalid on jvm")
ddef.vparamss.foreach(_.foreach { vparam =>
assert(vparam.symbol.is(Param),
diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala
index 9a6ecef51..44d26e7dd 100644
--- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala
+++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala
@@ -5,6 +5,7 @@ import core.Symbols._
import core.StdNames._
import ast.Trees._
import core.Types._
+import core.NameKinds.ExceptionBinderName
import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.core.Flags
import dotty.tools.dotc.core.Contexts.Context
@@ -83,7 +84,7 @@ class TryCatchPatterns extends MiniPhaseTransform {
implicit ctx: Context, info: TransformerInfo): Option[CaseDef] = {
if (patternMatchCases.isEmpty) None
else {
- val exName = ctx.freshName("ex").toTermName
+ val exName = ExceptionBinderName.fresh()
val fallbackSelector =
ctx.newSymbol(ctx.owner, exName, Flags.Synthetic | Flags.Case, defn.ThrowableType, coord = pos)
val sel = Ident(fallbackSelector.termRef).withPos(pos)
diff --git a/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala b/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala
index b16d05644..00d491486 100644
--- a/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala
@@ -8,6 +8,7 @@ import SymDenotations._
import Contexts._
import Flags._
import StdNames._
+import SymUtils._
/** Methods that apply to user-defined value classes */
object ValueClasses {
@@ -24,16 +25,13 @@ object ValueClasses {
d.isRealMethod &&
isDerivedValueClass(d.owner) &&
!d.isConstructor &&
- !d.is(SuperAccessor) &&
+ !d.isSuperAccessor &&
!d.is(Macro)
- /** The member that of a derived value class that unboxes it. */
+ /** The member of a derived value class that unboxes it. */
def valueClassUnbox(d: ClassDenotation)(implicit ctx: Context): Symbol =
// (info.decl(nme.unbox)).orElse(...) uncomment once we accept unbox methods
- d.classInfo.decls
- .find(d => d.isTerm && d.symbol.is(ParamAccessor))
- .map(_.symbol)
- .getOrElse(NoSymbol)
+ d.classInfo.decls.find(_.is(TermParamAccessor))
/** For a value class `d`, this returns the synthetic cast from the underlying type to
* ErasedValueType defined in the companion module. This method is added to the module
diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
index 8d926fcf0..baf1ae356 100644
--- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
+++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
@@ -13,6 +13,7 @@ import core.StdNames._
import core.NameOps._
import core.Constants._
import reporting.diagnostic.messages._
+import config.Printers.{ exhaustivity => debug }
/** Space logic for checking exhaustivity and unreachability of pattern matching
*
@@ -28,8 +29,6 @@ import reporting.diagnostic.messages._
* 3. A union of spaces `S1 | S2 | ...` is a space
* 4. For a case class Kon(x1: T1, x2: T2, .., xn: Tn), if S1, S2, ..., Sn
* are spaces, then `Kon(S1, S2, ..., Sn)` is a space.
- * 5. A constant `Const(value, T)` is a point in space
- * 6. A stable identifier `Var(sym, T)` is a space
*
* For the problem of exhaustivity check, its formulation in terms of space is as follows:
*
@@ -67,15 +66,6 @@ case class Kon(tp: Type, params: List[Space]) extends Space
/** Union of spaces */
case class Or(spaces: List[Space]) extends Space
-/** Point in space */
-sealed trait Point extends Space
-
-/** Point representing variables(stable identifier) in patterns */
-case class Var(sym: Symbol, tp: Type) extends Point
-
-/** Point representing literal constants in patterns */
-case class Const(value: Constant, tp: Type) extends Point
-
/** abstract space logic */
trait SpaceLogic {
/** Is `tp1` a subtype of `tp2`? */
@@ -97,6 +87,9 @@ trait SpaceLogic {
/** Get components of decomposable types */
def decompose(tp: Type): List[Space]
+ /** Display space in string format */
+ def show(sp: Space): String
+
/** Simplify space using the laws, there's no nested union after simplify */
def simplify(space: Space): Space = space match {
case Kon(tp, spaces) =>
@@ -137,7 +130,7 @@ trait SpaceLogic {
def tryDecompose1(tp: Type) = canDecompose(tp) && isSubspace(Or(decompose(tp)), b)
def tryDecompose2(tp: Type) = canDecompose(tp) && isSubspace(a, Or(decompose(tp)))
- (a, b) match {
+ val res = (a, b) match {
case (Empty, _) => true
case (_, Empty) => false
case (Or(ss), _) => ss.forall(isSubspace(_, b))
@@ -157,17 +150,11 @@ trait SpaceLogic {
simplify(minus(a, b)) == Empty
case (Kon(tp1, ss1), Kon(tp2, ss2)) =>
isEqualType(tp1, tp2) && ss1.zip(ss2).forall((isSubspace _).tupled)
- case (Const(v1, _), Const(v2, _)) => v1 == v2
- case (Const(_, tp1), Typ(tp2, _)) => isSubType(tp1, tp2) || tryDecompose2(tp2)
- case (Const(_, _), Or(ss)) => ss.exists(isSubspace(a, _))
- case (Const(_, _), _) => false
- case (_, Const(_, _)) => false
- case (Var(x, _), Var(y, _)) => x == y
- case (Var(_, tp1), Typ(tp2, _)) => isSubType(tp1, tp2) || tryDecompose2(tp2)
- case (Var(_, _), Or(ss)) => ss.exists(isSubspace(a, _))
- case (Var(_, _), _) => false
- case (_, Var(_, _)) => false
}
+
+ debug.println(s"${show(a)} < ${show(b)} = $res")
+
+ res
}
/** Intersection of two spaces */
@@ -175,7 +162,7 @@ trait SpaceLogic {
def tryDecompose1(tp: Type) = intersect(Or(decompose(tp)), b)
def tryDecompose2(tp: Type) = intersect(a, Or(decompose(tp)))
- (a, b) match {
+ val res = (a, b) match {
case (Empty, _) | (_, Empty) => Empty
case (_, Or(ss)) => Or(ss.map(intersect(a, _)).filterConserve(_ ne Empty))
case (Or(ss), _) => Or(ss.map(intersect(_, b)).filterConserve(_ ne Empty))
@@ -199,31 +186,11 @@ trait SpaceLogic {
if (!isEqualType(tp1, tp2)) Empty
else if (ss1.zip(ss2).exists(p => simplify(intersect(p._1, p._2)) == Empty)) Empty
else Kon(tp1, ss1.zip(ss2).map((intersect _).tupled))
- case (Const(v1, _), Const(v2, _)) =>
- if (v1 == v2) a else Empty
- case (Const(_, tp1), Typ(tp2, _)) =>
- if (isSubType(tp1, tp2)) a
- else if (canDecompose(tp2)) tryDecompose2(tp2)
- else Empty
- case (Const(_, _), _) => Empty
- case (Typ(tp1, _), Const(_, tp2)) =>
- if (isSubType(tp2, tp1)) b
- else if (canDecompose(tp1)) tryDecompose1(tp1)
- else Empty
- case (_, Const(_, _)) => Empty
- case (Var(x, _), Var(y, _)) =>
- if (x == y) a else Empty
- case (Var(_, tp1), Typ(tp2, _)) =>
- if (isSubType(tp1, tp2)) a
- else if (canDecompose(tp2)) tryDecompose2(tp2)
- else Empty
- case (Var(_, _), _) => Empty
- case (Typ(tp1, _), Var(_, tp2)) =>
- if (isSubType(tp2, tp1)) b
- else if (canDecompose(tp1)) tryDecompose1(tp1)
- else Empty
- case (_, Var(_, _)) => Empty
}
+
+ debug.println(s"${show(a)} & ${show(b)} = ${show(res)}")
+
+ res
}
/** The space of a not covered by b */
@@ -231,7 +198,7 @@ trait SpaceLogic {
def tryDecompose1(tp: Type) = minus(Or(decompose(tp)), b)
def tryDecompose2(tp: Type) = minus(a, Or(decompose(tp)))
- (a, b) match {
+ val res = (a, b) match {
case (Empty, _) => Empty
case (_, Empty) => a
case (Typ(tp1, _), Typ(tp2, _)) =>
@@ -264,26 +231,11 @@ trait SpaceLogic {
Or(ss1.zip(ss2).map((minus _).tupled).zip(0 to ss2.length - 1).map {
case (ri, i) => Kon(tp1, ss1.updated(i, ri))
})
- case (Const(v1, _), Const(v2, _)) =>
- if (v1 == v2) Empty else a
- case (Const(_, tp1), Typ(tp2, _)) =>
- if (isSubType(tp1, tp2)) Empty
- else if (canDecompose(tp2)) tryDecompose2(tp2)
- else a
- case (Const(_, _), _) => a
- case (Typ(tp1, _), Const(_, tp2)) => // Boolean & Java enum
- if (canDecompose(tp1)) tryDecompose1(tp1)
- else a
- case (_, Const(_, _)) => a
- case (Var(x, _), Var(y, _)) =>
- if (x == y) Empty else a
- case (Var(_, tp1), Typ(tp2, _)) =>
- if (isSubType(tp1, tp2)) Empty
- else if (canDecompose(tp2)) tryDecompose2(tp2)
- else a
- case (Var(_, _), _) => a
- case (_, Var(_, _)) => a
}
+
+ debug.println(s"${show(a)} - ${show(b)} = ${show(res)}")
+
+ res
}
}
@@ -297,19 +249,14 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
* otherwise approximate extractors to Empty
*/
def project(pat: Tree, roundUp: Boolean = true)(implicit ctx: Context): Space = pat match {
- case Literal(c) => Const(c, c.tpe)
- case _: BackquotedIdent => Var(pat.symbol, pat.tpe)
+ case Literal(c) =>
+ if (c.value.isInstanceOf[Symbol])
+ Typ(c.value.asInstanceOf[Symbol].termRef, false)
+ else
+ Typ(ConstantType(c), false)
+ case _: BackquotedIdent => Typ(pat.tpe, false)
case Ident(_) | Select(_, _) =>
- pat.tpe.stripAnnots match {
- case tp: TermRef =>
- if (pat.symbol.is(Enum))
- Const(Constant(pat.symbol), tp)
- else if (tp.underlyingIterator.exists(_.classSymbol.is(Module)))
- Typ(tp.widenTermRefExpr.stripAnnots, false)
- else
- Var(pat.symbol, tp)
- case tp => Typ(tp, false)
- }
+ Typ(pat.tpe.stripAnnots, false)
case Alternative(trees) => Or(trees.map(project(_, roundUp)))
case Bind(_, pat) => project(pat)
case UnApply(_, _, pats) =>
@@ -345,7 +292,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
/** Is `tp1` a subtype of `tp2`? */
def isSubType(tp1: Type, tp2: Type): Boolean = {
// check SI-9657 and tests/patmat/gadt.scala
- erase(tp1) <:< erase(tp2)
+ val res = erase(tp1) <:< erase(tp2)
+ debug.println(s"${tp1.show} <:< ${tp2.show} = $res")
+ res
}
def isEqualType(tp1: Type, tp2: Type): Boolean = tp1 =:= tp2
@@ -373,19 +322,23 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
}
}
+ debug.println(s"candidates for ${tp.show} : [${children.map(_.show).mkString(", ")}]")
+
tp match {
case OrType(tp1, tp2) => List(Typ(tp1, true), Typ(tp2, true))
case _ if tp =:= ctx.definitions.BooleanType =>
List(
- Const(Constant(true), ctx.definitions.BooleanType),
- Const(Constant(false), ctx.definitions.BooleanType)
+ Typ(ConstantType(Constant(true)), true),
+ Typ(ConstantType(Constant(false)), true)
)
case _ if tp.classSymbol.is(Enum) =>
- children.map(sym => Const(Constant(sym), tp))
+ children.map(sym => Typ(sym.termRef, true))
case _ =>
val parts = children.map { sym =>
if (sym.is(ModuleClass))
- sym.asClass.classInfo.selfType
+ refine(tp, sym.sourceModule.termRef)
+ else if (sym.isTerm)
+ refine(tp, sym.termRef)
else if (sym.info.typeParams.length > 0 || tp.isInstanceOf[TypeRef])
refine(tp, sym.typeRef)
else
@@ -393,9 +346,13 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
} filter { tpe =>
// Child class may not always be subtype of parent:
// GADT & path-dependent types
- tpe <:< expose(tp)
+ val res = tpe <:< expose(tp)
+ if (!res) debug.println(s"unqualified child ousted: ${tpe.show} !< ${tp.show}")
+ res
}
+ debug.println(s"${tp.show} decomposes to [${parts.map(_.show).mkString(", ")}]")
+
parts.map(Typ(_, true))
}
}
@@ -409,20 +366,26 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
* `path2`, then return `path1.B`.
*/
def refine(tp1: Type, tp2: Type): Type = (tp1, tp2) match {
- case (tp1: RefinedType, _) => tp1.wrapIfMember(refine(tp1.parent, tp2))
+ case (tp1: RefinedType, _: TypeRef) => tp1.wrapIfMember(refine(tp1.parent, tp2))
case (tp1: HKApply, _) => refine(tp1.superType, tp2)
- case (TypeRef(ref1: TypeProxy, _), tp2 @ TypeRef(ref2: TypeProxy, name)) =>
- if (ref1.underlying <:< ref2.underlying) TypeRef(ref1, name) else tp2
+ case (TypeRef(ref1: TypeProxy, _), tp2 @ TypeRef(ref2: TypeProxy, _)) =>
+ if (ref1.underlying <:< ref2.underlying) tp2.derivedSelect(ref1) else tp2
+ case (TypeRef(ref1: TypeProxy, _), tp2 @ TermRef(ref2: TypeProxy, _)) =>
+ if (ref1.underlying <:< ref2.underlying) tp2.derivedSelect(ref1) else tp2
case _ => tp2
}
/** Abstract sealed types, or-types, Boolean and Java enums can be decomposed */
def canDecompose(tp: Type): Boolean = {
- tp.classSymbol.is(allOf(Abstract, Sealed)) ||
+ val res = tp.classSymbol.is(allOf(Abstract, Sealed)) ||
tp.classSymbol.is(allOf(Trait, Sealed)) ||
tp.isInstanceOf[OrType] ||
tp =:= ctx.definitions.BooleanType ||
- tp.classSymbol.is(Enum)
+ tp.classSymbol.is(allOf(Enum, Sealed)) // Enum value doesn't have Sealed flag
+
+ debug.println(s"decomposable: ${tp.show} = $res")
+
+ res
}
/** Show friendly type name with current scope in mind
@@ -474,14 +437,12 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
def show(s: Space): String = {
def doShow(s: Space, mergeList: Boolean = false): String = s match {
case Empty => ""
- case Const(v, _) => v.show
- case Var(x, _) => x.show
+ case Typ(c: ConstantType, _) => c.value.show
+ case Typ(tp: TermRef, _) => tp.symbol.showName
case Typ(tp, decomposed) =>
val sym = tp.widen.classSymbol
- if (sym.is(ModuleClass))
- showType(tp)
- else if (ctx.definitions.isTupleType(tp))
+ if (ctx.definitions.isTupleType(tp))
signature(tp).map(_ => "_").mkString("(", ", ", ")")
else if (sym.showFullName == "scala.collection.immutable.::")
if (mergeList) "_" else "List(_)"
@@ -523,7 +484,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
}
val Match(sel, cases) = tree
- isCheckable(sel.tpe.widen.deAnonymize.dealiasKeepAnnots)
+ val res = isCheckable(sel.tpe.widen.deAnonymize.dealiasKeepAnnots)
+ debug.println(s"checkable: ${sel.show} = $res")
+ res
}
@@ -584,7 +547,11 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
val selTyp = sel.tpe.widen.deAnonymize.dealias
- val patternSpace = cases.map(x => project(x.pat)).reduce((a, b) => Or(List(a, b)))
+ val patternSpace = cases.map({ x =>
+ val space = project(x.pat)
+ debug.println(s"${x.pat.show} projects to ${show(space)}")
+ space
+ }).reduce((a, b) => Or(List(a, b)))
val uncovered = simplify(minus(Typ(selTyp, true), patternSpace))
if (uncovered != Empty)