From 24f40bc76493410f2688c8a74028ecb1db7306bf Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 31 Mar 2017 14:40:06 +0200 Subject: Make outer select names semantic --- compiler/src/dotty/tools/dotc/core/NameKinds.scala | 10 ++++++++++ compiler/src/dotty/tools/dotc/core/NameOps.scala | 8 -------- compiler/src/dotty/tools/dotc/core/StdNames.scala | 1 - compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala | 2 ++ compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala | 10 ++++++---- compiler/src/dotty/tools/dotc/transform/FirstTransform.scala | 4 ++-- compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala | 4 ++-- compiler/src/dotty/tools/dotc/transform/TreeChecker.scala | 3 ++- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 9 +++------ 9 files changed, 27 insertions(+), 24 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 8279c21bb..cabb83171 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -242,6 +242,16 @@ object NameKinds { } } + /** Names of the form N_. Emitted by inliner, replaced by outer path + * in ExplicitOuter. + */ + object OuterSelectName extends NumberedNameKind(OUTERSELECT, "OuterSelect") { + def mkString(underlying: TermName, info: ThisInfo) = { + assert(underlying.isEmpty) + info.num + "_" + } + } + val SuperAccessorName = new PrefixNameKind(SUPERACCESSOR, "super$") val InitializerName = new PrefixNameKind(INITIALIZER, "initial$") val ShadowedName = new PrefixNameKind(SHADOWED, "(shadowed)") diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index b262fb536..44c5c1e09 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -60,11 +60,9 @@ object NameOps { def isLocalDummyName = name startsWith LOCALDUMMY_PREFIX def isReplWrapperName = name.toSimpleName containsSlice INTERPRETER_IMPORT_WRAPPER def isSetterName = name endsWith SETTER_SUFFIX - def isImportName = name startsWith IMPORT def isScala2LocalSuffix = name.endsWith(" ") def isModuleVarName(name: Name): Boolean = name.exclude(UniqueName).is(ModuleVarName) def isSelectorName = name.startsWith("_") && name.tail.forall(_.isDigit) - def isOuterSelect = name.endsWith(nme.OUTER_SELECT) /** Is name a variable name? */ def isVariableName: Boolean = name.length > 0 && { @@ -247,12 +245,6 @@ object NameOps { else -1 } - /** The number of hops specified in an outer-select name */ - def outerSelectHops: Int = { - require(isOuterSelect) - name.dropRight(nme.OUTER_SELECT.length).toString.toInt - } - /** The name of the generic runtime operation corresponding to an array operation */ def genericArrayOp: TermName = name match { case nme.apply => nme.array_apply diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index b89775e9e..b5d8e356e 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -253,7 +253,6 @@ object StdNames { val MODULE_INSTANCE_FIELD: N = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$" val OUTER: N = "$outer" val OUTER_LOCAL: N = "$outer " - val OUTER_SELECT: N = "_" // emitted by inliner, replaced by outer path in explicitouter val REFINE_CLASS: N = "" val ROOTPKG: N = "_root_" val SELECTOR_DUMMY: N = "" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 04550f188..68c5bf10e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -229,6 +229,8 @@ object TastyFormat { final val UNIQUE = 10 final val DEFAULTGETTER = 11 final val VARIANT = 12 + final val OUTERSELECT = 13 + final val SUPERACCESSOR = 20 final val PROTECTEDACCESSOR = 21 final val PROTECTEDSETTER = 22 diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index a6e643992..c302aa61b 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_` 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. diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index 37f978f11..a3cf71ef2 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -20,7 +20,7 @@ import scala.collection.mutable import DenotTransformers._ import typer.Checking import NameOps._ -import NameKinds.AvoidClashName +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 => diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 583834fb3..80d9091fb 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -11,7 +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} +import NameKinds.{ProtectedAccessorName, ProtectedSetterName, OuterSelectName} import Symbols._, TypeUtils._ /** This class performs the following functions: @@ -152,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 diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 9bb00e683..44c26ecd9 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 @@ -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 = diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index eaabb0689..38a139be1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -13,9 +13,9 @@ import Decorators._ import Constants._ import StdNames.nme import Contexts.Context -import Names.{Name, TermName} +import Names.{Name, TermName, EmptyTermName} import NameOps._ -import NameKinds.InlineAccessorName +import NameKinds.{InlineAccessorName, OuterSelectName} import SymDenotations.SymDenotation import Annotations._ import transform.ExplicitOuter @@ -399,9 +399,6 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { // The class that the this-proxy `selfSym` represents def classOf(selfSym: Symbol) = selfSym.info.widen.classSymbol - // The name of the outer selector that computes the rhs of `selfSym` - def outerSelector(n: Int): TermName = n.toString.toTermName ++ nme.OUTER_SELECT - // The total nesting depth of the class represented by `selfSym`. def outerLevel(selfSym: Symbol): Int = classOf(selfSym).ownersIterator.length @@ -419,7 +416,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { if (!lastSelf.exists) prefix else - untpd.Select(ref(lastSelf), outerSelector(lastLevel - level)).withType(selfSym.info) + untpd.Select(ref(lastSelf), OuterSelectName(EmptyTermName, lastLevel - level)).withType(selfSym.info) bindingsBuf += ValDef(selfSym.asTerm, rhs) lastSelf = selfSym lastLevel = level -- cgit v1.2.3