diff options
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform')
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) |