Skip to content

Commit 6f8ce61

Browse files
committed
Use unencoded names internally
Don't encode operator symbols internally. Instead, let the backend convert them when generating code. # Conflicts: # compiler/src/dotty/tools/dotc/core/Names.scala # compiler/src/dotty/tools/dotc/core/StdNames.scala # compiler/src/dotty/tools/dotc/transform/PostTyper.scala # Conflicts: # compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala # compiler/src/dotty/tools/dotc/core/Names.scala
1 parent d3850c8 commit 6f8ce61

20 files changed

+159
-192
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class Definitions {
137137
}
138138

139139
private def newMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol =
140-
newSymbol(cls, name.encode, flags | Method, info).asTerm
140+
newSymbol(cls, name, flags | Method, info).asTerm
141141

142142
private def enterMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol =
143143
newMethod(cls, name, info, flags).entered
@@ -301,7 +301,7 @@ class Definitions {
301301
lazy val ScalaPredefModuleRef = ctx.requiredModuleRef("scala.Predef")
302302
def ScalaPredefModule(implicit ctx: Context) = ScalaPredefModuleRef.symbol
303303

304-
lazy val Predef_ConformsR = ScalaPredefModule.requiredClass("$less$colon$less").typeRef
304+
lazy val Predef_ConformsR = ScalaPredefModule.requiredClass("<:<").typeRef
305305
def Predef_Conforms(implicit ctx: Context) = Predef_ConformsR.symbol
306306
lazy val Predef_conformsR = ScalaPredefModule.requiredMethodRef("$conforms")
307307
def Predef_conforms(implicit ctx: Context) = Predef_conformsR.symbol

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

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import printing.{Showable, Texts, Printer}
88
import Texts.Text
99
import Decorators._
1010
import Contexts.Context
11+
import StdNames.str
1112
import collection.IndexedSeqOptimized
1213
import collection.generic.CanBuildFrom
1314
import collection.mutable.{ Builder, StringBuilder, AnyRefMap }
@@ -67,7 +68,17 @@ object Names {
6768
def isSimple: Boolean
6869
def asSimpleName: SimpleTermName
6970
def toSimpleName: SimpleTermName
70-
def mangled: Name
71+
72+
@sharable // because it's just a cache for performance
73+
private[this] var myMangled: Name = null
74+
75+
protected[Names] def mangle: ThisName
76+
77+
final def mangled: ThisName = {
78+
if (myMangled == null) myMangled = mangle
79+
myMangled.asInstanceOf[ThisName]
80+
}
81+
7182
def mangledString: String = mangled.toString
7283

7384
def rewrite(f: PartialFunction[Name, Name]): ThisName
@@ -268,7 +279,7 @@ object Names {
268279
def isSimple = true
269280
def asSimpleName = this
270281
def toSimpleName = this
271-
def mangled = this
282+
final def mangle = encode
272283

273284
def rewrite(f: PartialFunction[Name, Name]): ThisName =
274285
if (f.isDefinedAt(this)) likeSpaced(f(this)) else this
@@ -277,11 +288,10 @@ object Names {
277288
def mapParts(f: SimpleTermName => SimpleTermName) = f(this)
278289

279290
def encode: SimpleTermName =
280-
if (dontEncode(toTermName)) this else NameTransformer.encode(this)
291+
if (dontEncode(this)) this else NameTransformer.encode(this)
281292

282293
/** Replace \$op_name's by corresponding operator symbols. */
283-
def decode: SimpleTermName =
284-
if (contains('$')) termName(NameTransformer.decode(toString)) else this
294+
def decode: SimpleTermName = NameTransformer.decode(this)
285295

286296
def firstPart = this
287297
def lastPart = this
@@ -324,6 +334,9 @@ object Names {
324334
.contains(elem.getMethodName))
325335
}
326336

337+
def sliceToString(from: Int, end: Int) =
338+
if (end <= from) "" else new String(chrs, start + from, end - from)
339+
327340
def debugString: String = toString
328341
}
329342

@@ -346,7 +359,7 @@ object Names {
346359
def isSimple = toTermName.isSimple
347360
def asSimpleName = toTermName.asSimpleName
348361
def toSimpleName = toTermName.toSimpleName
349-
def mangled = toTermName.toSimpleName.toTypeName
362+
final def mangle = toTermName.mangle.toTypeName
350363

351364
def rewrite(f: PartialFunction[Name, Name]): ThisName = toTermName.rewrite(f).toTypeName
352365
def collect[T](f: PartialFunction[Name, T]): Option[T] = toTermName.collect(f)
@@ -382,12 +395,8 @@ object Names {
382395
def isSimple = false
383396
def asSimpleName = throw new UnsupportedOperationException(s"$debugString is not a simple name")
384397

385-
private[this] var simpleName: SimpleTermName = null
386-
def toSimpleName = {
387-
if (simpleName == null) simpleName = termName(toString)
388-
simpleName
389-
}
390-
def mangled = toSimpleName
398+
def toSimpleName = termName(toString)
399+
final def mangle = encode.toSimpleName
391400

392401
def rewrite(f: PartialFunction[Name, Name]): ThisName =
393402
if (f.isDefinedAt(this)) likeSpaced(f(this))
@@ -556,8 +565,13 @@ object Names {
556565
val STATIC_CONSTRUCTOR: TermName = termName("<clinit>")
557566
val EMPTY_PACKAGE: TermName = termName("<empty>")
558567
val REFINEMENT: TermName = termName("<refinement>")
568+
val LOCALDUMMY_PREFIX: TermName = termName("<local ")
569+
570+
val dontEncodeNames = Set(CONSTRUCTOR, STATIC_CONSTRUCTOR, EMPTY_PACKAGE, REFINEMENT)
559571

560-
val dontEncode = Set(CONSTRUCTOR, EMPTY_PACKAGE, REFINEMENT)
572+
def dontEncode(name: SimpleTermName) =
573+
name.length > 0 && name(0) == '<' &&
574+
(dontEncodeNames.contains(name) || name.startsWith(str.LOCALDUMMY_PREFIX))
561575

562576
implicit val NameOrdering: Ordering[Name] = new Ordering[Name] {
563577
private def compareInfos(x: NameInfo, y: NameInfo): Int =

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

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ object StdNames {
1616
/** Base strings from which synthetic names are derived. */
1717

1818
object str {
19-
final val SETTER_SUFFIX = "_$eq"
19+
final val SETTER_SUFFIX = "_="
2020
final val EXPAND_SEPARATOR = "$$"
2121
final val TRAIT_SETTER_SEPARATOR = "$_setter_$"
2222
final val SUPER_PREFIX = "super$"
2323
final val INITIALIZER_PREFIX = "initial$"
2424
final val SHADOWED_PREFIX = "(shadowed)"
2525
final val AVOID_CLASH_SUFFIX = "$_avoid_name_clash_$"
26-
final val MODULE_SUFFIX = NameTransformer.MODULE_SUFFIX_STRING
26+
final val MODULE_SUFFIX = "$"
27+
//final val NAME_JOIN = "$"
2728
final val DEFAULT_GETTER = "$default$"
2829
final val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
2930
final val ANON_CLASS = "$anon"
@@ -131,8 +132,7 @@ object StdNames {
131132
val EXPAND_SEPARATOR: N = str.EXPAND_SEPARATOR
132133
val IMPL_CLASS_SUFFIX: N = "$class"
133134
val IMPORT: N = "<import>"
134-
val MODULE_SUFFIX: N = NameTransformer.MODULE_SUFFIX_STRING
135-
val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING
135+
val MODULE_SUFFIX: N = str.MODULE_SUFFIX
136136
val OPS_PACKAGE: N = "<special-ops>"
137137
val OVERLOADED: N = "<overloaded>"
138138
val PACKAGE: N = "package"
@@ -259,7 +259,7 @@ object StdNames {
259259
val REIFY_FREE_THIS_SUFFIX: N = "$this"
260260
val REIFY_FREE_VALUE_SUFFIX: N = "$value"
261261
val REIFY_SYMDEF_PREFIX: N = "symdef$"
262-
val MODULE_INSTANCE_FIELD: N = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
262+
val MODULE_INSTANCE_FIELD: N = "MODULE$"
263263
val OUTER: N = "$outer"
264264
val REFINE_CLASS: N = "<refinement>"
265265
val ROOTPKG: N = "_root_"
@@ -310,7 +310,7 @@ object StdNames {
310310
val _21 : N = "_21"
311311
val _22 : N = "_22"
312312

313-
val ??? = encode("???")
313+
val ??? : N = "???"
314314

315315
val genericWrapArray: N = "genericWrapArray"
316316
def wrapRefArray: N = "wrapRefArray"
@@ -595,36 +595,36 @@ object StdNames {
595595
def newLazyValSlowComputeName(lzyValName: N) = lzyValName ++ LAZY_SLOW_SUFFIX
596596

597597
// ASCII names for operators
598-
val ADD = encode("+")
599-
val AND = encode("&")
600-
val ASR = encode(">>")
601-
val DIV = encode("/")
602-
val EQ = encode("==")
603-
val EQL = encode("=")
604-
val GE = encode(">=")
605-
val GT = encode(">")
606-
val HASHHASH = encode("##")
607-
val LE = encode("<=")
608-
val LSL = encode("<<")
609-
val LSR = encode(">>>")
610-
val LT = encode("<")
611-
val MINUS = encode("-")
612-
val MOD = encode("%")
613-
val MUL = encode("*")
614-
val NE = encode("!=")
615-
val OR = encode("|")
598+
val ADD : N = "+"
599+
val AND : N = "&"
600+
val ASR : N = ">>"
601+
val DIV : N = "/"
602+
val EQ : N = "=="
603+
val EQL : N = "="
604+
val GE : N = ">="
605+
val GT : N = ">"
606+
val HASHHASH : N = "##"
607+
val LE : N = "<="
608+
val LSL : N = "<<"
609+
val LSR : N = ">>>"
610+
val LT : N = "<"
611+
val MINUS : N = "-"
612+
val MOD : N = "%"
613+
val MUL : N = "*"
614+
val NE : N = "!="
615+
val OR : N = "|"
616616
val PLUS = ADD // technically redundant, but ADD looks funny with MINUS
617617
val SUB = MINUS // ... as does SUB with PLUS
618-
val XOR = encode("^")
619-
val ZAND = encode("&&")
620-
val ZOR = encode("||")
618+
val XOR : N = "^"
619+
val ZAND : N = "&&"
620+
val ZOR : N = "||"
621621

622622
// unary operators
623623
val UNARY_PREFIX: N = "unary_"
624-
val UNARY_~ = encode("unary_~")
625-
val UNARY_+ = encode("unary_+")
626-
val UNARY_- = encode("unary_-")
627-
val UNARY_! = encode("unary_!")
624+
val UNARY_~ : N = "unary_~"
625+
val UNARY_+ : N = "unary_+"
626+
val UNARY_- : N = "unary_-"
627+
val UNARY_! : N = "unary_!"
628628

629629
// Grouped here so Cleanup knows what tests to perform.
630630
val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE)

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,7 @@ object SymDenotations {
369369
/** The expanded name of this denotation. */
370370
final def expandedName(implicit ctx: Context) =
371371
if (name.is(ExpandedName) || isConstructor) name
372-
else {
373-
def legalize(name: Name): Name = // JVM method names may not contain `<' or `>' characters
374-
if (is(Method)) name.replace('<', '(').replace('>', ')') else name
375-
legalize(name.expandedName(initial.owner))
376-
}
372+
else name.expandedName(initial.owner)
377373
// need to use initial owner to disambiguate, as multiple private symbols with the same name
378374
// might have been moved from different origins into the same class
379375

compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class TastyUnpickler(reader: TastyReader) {
4848
val result = tag match {
4949
case UTF8 =>
5050
goto(end)
51-
termName(bytes, start.index, length)
51+
termName(bytes, start.index, length).decode
5252
case QUALIFIED | FLATTENED | EXPANDED | EXPANDPREFIX =>
5353
qualifiedNameKindOfTag(tag)(readName(), readName().asSimpleName)
5454
case UNIQUE =>

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
338338
def atEnd = readIndex == end
339339

340340
def readExtSymbol(): Symbol = {
341-
val name = readNameRef()
341+
val name = readNameRef().decode
342342
val owner = if (atEnd) loadingMirror.RootClass else readSymbolRef()
343343

344344
def adjust(denot: Denotation) = {
@@ -401,7 +401,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
401401
// println(owner.info.decls.toList.map(_.debugString).mkString("\n ")) // !!! DEBUG
402402
// }
403403
// (5) Create a stub symbol to defer hard failure a little longer.
404-
System.err.println(i"***** missing reference, looking for $name in $owner")
404+
System.err.println(i"***** missing reference, looking for ${name.debugString} in $owner")
405405
System.err.println(i"decls = ${owner.info.decls}")
406406
owner.info.decls.checkConsistent()
407407
if (slowSearch(name).exists)
@@ -447,6 +447,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
447447
name = name.asTermName.unmangle(SuperAccessorName)
448448
flags = flags &~ Scala2SuperAccessor
449449
}
450+
name = name.mapLast(_.decode)
450451

451452
val mname = name.mangled
452453
def nameMatches(rootName: Name) = mname == rootName.mangled

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import core.StdNames._, core.Comments._
77
import util.SourceFile
88
import java.lang.Character.isDigit
99
import util.Chars._
10+
import util.NameTransformer.avoidIllegalChars
1011
import Tokens._
1112
import scala.annotation.{ switch, tailrec }
1213
import scala.collection.mutable
@@ -622,6 +623,7 @@ object Scanners {
622623
if (ch == '`') {
623624
nextChar()
624625
finishNamed(BACKQUOTED_IDENT)
626+
name = avoidIllegalChars(name)
625627
if (name.length == 0)
626628
error("empty quoted identifier")
627629
else if (name == nme.WILDCARD)

compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont
5454
val __Text: TermName = "Text"
5555
val _buf: TermName = "$buf"
5656
val _md: TermName = "$md"
57-
val _plus: TermName = "$amp$plus"
57+
val _plus: TermName = "&+"
5858
val _tmpscope: TermName = "$tmpscope"
5959
val _xml: TermName = "xml"
6060
}

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
6060
protected val PrintableFlags = (SourceModifierFlags | Label | Module | Local).toCommonFlags
6161

6262
override def nameString(name: Name): String =
63-
if (ctx.settings.debugNames.value) name.debugString else name.decode.toString
63+
if (ctx.settings.debugNames.value) name.debugString else name.toString
6464

6565
override protected def simpleNameString(sym: Symbol): String = {
6666
val name = if (ctx.property(XprintMode).isEmpty) sym.originalName else sym.name

compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ class CompilingInterpreter(
742742
override def shouldShowResult(req: Request): Boolean =
743743
!statement.mods.is(Flags.AccessFlags) &&
744744
!(isGeneratedVarName(statement.name.toString) &&
745-
req.typeOf(statement.name.encode) == "Unit")
745+
req.typeOf(statement.name) == "Unit")
746746
}
747747

748748

@@ -812,7 +812,7 @@ class CompilingInterpreter(
812812
/** Print out lhs instead of the generated varName */
813813
override def resultExtractionCode(req: Request, code: PrintWriter): Unit = {
814814
code.print(" + \"" + lhs.show + ": " +
815-
string2code(req.typeOf(helperName.encode)) +
815+
string2code(req.typeOf(helperName)) +
816816
" = \" + " +
817817
string2code(req.fullPath(helperName))
818818
+ " + \"\\n\"")

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
265265
case Import(expr, selectors) =>
266266
val exprTpe = expr.tpe
267267
def checkIdent(ident: untpd.Ident): Unit = {
268-
val name = ident.name.asTermName.encode
268+
val name = ident.name.asTermName
269269
if (name != nme.WILDCARD && !exprTpe.member(name).exists && !exprTpe.member(name.toTypeName).exists)
270270
ctx.error(s"${ident.name} is not a member of ${expr.show}", ident.pos)
271271
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
107107
// ParamForwaders as installed ParamForwarding.scala do use super calls to vals
108108
ctx.error(s"super may be not be used on ${sym.underlyingSymbol}", sel.pos)
109109
else if (isDisallowed(sym))
110-
ctx.error(s"super not allowed here: use this.${sel.name.decode} instead", sel.pos)
110+
ctx.error(s"super not allowed here: use this.${sel.name} instead", sel.pos)
111111
else if (sym is Deferred) {
112112
val member = sym.overridingSymbol(clazz)
113113
if (!mix.name.isEmpty ||

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class SyntheticMethods(thisTransformer: DenotTransformer) {
8282
ref(defn.runtimeMethodRef("_" + sym.name.toString)).appliedToArgs(This(clazz) :: vrefss.head)
8383

8484
def ownName(vrefss: List[List[Tree]]): Tree =
85-
Literal(Constant(clazz.name.stripModuleClassSuffix.decode.toString))
85+
Literal(Constant(clazz.name.stripModuleClassSuffix.toString))
8686

8787
def syntheticRHS(implicit ctx: Context): List[List[Tree]] => Tree = synthetic.name match {
8888
case nme.hashCode_ if isDerivedValueClass(clazz) => vrefss => valueHashCodeBody

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import reporting.ThrowingReporter
2525
import ast.Trees._
2626
import ast.{tpd, untpd}
2727
import util.SourcePosition
28+
import util.Chars._
2829
import collection.mutable
2930
import ProtoTypes._
3031
import config.Printers
@@ -51,11 +52,9 @@ class TreeChecker extends Phase with SymTransformer {
5152
private val seenClasses = collection.mutable.HashMap[String, Symbol]()
5253
private val seenModuleVals = collection.mutable.HashMap[String, Symbol]()
5354

54-
def isValidJVMName(name: Name) =
55-
!name.toString.exists(c => c == '.' || c == ';' || c =='[' || c == '/')
55+
def isValidJVMName(name: Name) = name.toString.forall(isValidJVMChar)
5656

57-
def isValidJVMMethodName(name: Name) =
58-
!name.toString.exists(c => c == '.' || c == ';' || c =='[' || c == '/' || c == '<' || c == '>')
57+
def isValidJVMMethodName(name: Name) = name.toString.forall(isValidJVMMethodChar)
5958

6059
def printError(str: String)(implicit ctx: Context) = {
6160
ctx.echo(Console.RED + "[error] " + Console.WHITE + str)
@@ -149,7 +148,7 @@ class TreeChecker extends Phase with SymTransformer {
149148
def withDefinedSym[T](tree: untpd.Tree)(op: => T)(implicit ctx: Context): T = tree match {
150149
case tree: untpd.DefTree =>
151150
val sym = tree.symbol
152-
assert(isValidJVMName(sym.name), s"${sym.fullName} name is invalid on jvm")
151+
assert(isValidJVMName(sym.name.encode), s"${sym.name.debugString} name is invalid on jvm")
153152
everDefinedSyms.get(sym) match {
154153
case Some(t) =>
155154
if (t ne tree)
@@ -386,7 +385,7 @@ class TreeChecker extends Phase with SymTransformer {
386385
withDefinedSyms(ddef.tparams) {
387386
withDefinedSymss(ddef.vparamss) {
388387
if (!sym.isClassConstructor && !(sym.name eq Names.STATIC_CONSTRUCTOR))
389-
assert(isValidJVMMethodName(sym.name), s"${sym.name.debugString} name is invalid on jvm")
388+
assert(isValidJVMMethodName(sym.name.encode), s"${sym.name.debugString} name is invalid on jvm")
390389

391390
ddef.vparamss.foreach(_.foreach { vparam =>
392391
assert(vparam.symbol.is(Param),

0 commit comments

Comments
 (0)