Skip to content

Commit cf6b62f

Browse files
committed
Avoid name clashes when generating synthetic companion objects.
1 parent 8487143 commit cf6b62f

File tree

5 files changed

+31
-7
lines changed

5 files changed

+31
-7
lines changed

src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ object NameOps {
7272
def isSetterName = name endsWith SETTER_SUFFIX
7373
def isSingletonName = name endsWith SINGLETON_SUFFIX
7474
def isModuleClassName = name endsWith MODULE_SUFFIX
75+
def isAvoidClashName = name endsWith AVOID_CLASH_SUFFIX
7576
def isImportName = name startsWith IMPORT
7677
def isFieldName = name endsWith LOCAL_SUFFIX
7778
def isInheritedName = name.length > 0 && name.head == '(' && name.startsWith(nme.INHERITED)
@@ -129,11 +130,19 @@ object NameOps {
129130
/** If name ends in module class suffix, drop it */
130131
def stripModuleClassSuffix: Name =
131132
if (isModuleClassName) name dropRight MODULE_SUFFIX.length else name
133+
134+
/** Append a suffix so that this name does not clash with another name in the same scope */
135+
def avoidClashName: TermName = (name ++ AVOID_CLASH_SUFFIX).toTermName
136+
137+
/** If name ends in "avoid clash" suffix, drop it */
138+
def stripAvoidClashSuffix: Name =
139+
if (isAvoidClashName) name dropRight AVOID_CLASH_SUFFIX.length else name
132140

133141
/** If flags is a ModuleClass but not a Package, add module class suffix */
134-
def adjustIfModuleClass(flags: Flags.FlagSet): N =
135-
if (flags is (ModuleClass, butNot = Package)) name.asTypeName.moduleClassName.asInstanceOf[N]
136-
else name
142+
def adjustIfModuleClass(flags: Flags.FlagSet): N = {
143+
if (flags is (ModuleClass, butNot = Package)) name.asTypeName.moduleClassName
144+
else stripAvoidClashSuffix
145+
}.asInstanceOf[N]
137146

138147
/** The superaccessor for method with given name */
139148
def superName: TermName = (nme.SUPER_PREFIX ++ name).toTermName

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ object StdNames {
107107
val INTERPRETER_WRAPPER_SUFFIX: N = "$object"
108108
val LOCALDUMMY_PREFIX: N = "<local " // owner of local blocks
109109
val MODULE_SUFFIX: N = NameTransformer.MODULE_SUFFIX_STRING
110+
val AVOID_CLASH_SUFFIX: N = "$_avoid_name_clash_$"
110111
val MODULE_VAR_SUFFIX: N = "$module"
111112
val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING
112113
val USCORE_PARAM_PREFIX: N = "_$"

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,14 @@ object SymDenotations {
171171
myInfo = tp
172172
}
173173

174-
/** The name, except if this is a module class, strip the module class suffix */
174+
/** The name, except
175+
* - if this is a module class, strip the module class suffix
176+
* - if this is a companion object with a clash-avoiding name, strip the
177+
* "avoid clash" suffix
178+
*/
175179
def effectiveName(implicit ctx: Context) =
176-
if (this is ModuleClass) name.stripModuleClassSuffix else name
180+
if (this is ModuleClass) name.stripModuleClassSuffix
181+
else name.stripAvoidClashSuffix
177182

178183
/** The privateWithin boundary, NoSymbol if no boundary is given.
179184
*/

src/dotty/tools/dotc/transform/FirstTransform.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,15 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
8181

8282
def addMissingCompanions(stats: List[Tree]): List[Tree] = stats map {
8383
case stat: TypeDef if singleClassDefs contains stat.name =>
84-
Thicket(stat :: newCompanion(stat.name.toTermName).trees)
84+
val objName = stat.name.toTermName
85+
val nameClash = stats.exists {
86+
case other: MemberDef =>
87+
other.name == objName && other.symbol.info.isParameterless
88+
case _ =>
89+
false
90+
}
91+
val uniqueName = if (nameClash) objName.avoidClashName else objName
92+
Thicket(stat :: newCompanion(uniqueName).trees)
8593
case stat => stat
8694
}
8795

tests/pending/pos/S5.scala renamed to tests/new/S5.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
/* Here's a fragment of a Scala encoding for the Keris module system;
1+
/* Original comment:
2+
* Here's a fragment of a Scala encoding for the Keris module system;
23
** the compiler claims:
34
**
45
** S5.scala:28: value n in class N of type N.this._N.n

0 commit comments

Comments
 (0)