Skip to content

Commit d07e5d1

Browse files
committed
Merge pull request #719 from dotty-staging/fix/doubledefs
Avoid crashes on double definitions
2 parents 1f45c67 + 5feab11 commit d07e5d1

File tree

5 files changed

+31
-25
lines changed

5 files changed

+31
-25
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import scala.annotation.switch
66
import scala.io.Codec
77
import Names._, StdNames._, Contexts._, Symbols._, Flags._
88
import Decorators.StringDecorator
9-
import dotty.tools.dotc.util.Chars
9+
import util.{Chars, NameTransformer}
1010
import Chars.isOperatorPart
1111

1212
object NameOps {
@@ -59,7 +59,7 @@ object NameOps {
5959
implicit class NameDecorator[N <: Name](val name: N) extends AnyVal {
6060
import nme._
6161

62-
def likeTyped(n: Name): N =
62+
def likeTyped(n: PreName): N =
6363
(if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N]
6464

6565
def isConstructorName = name == CONSTRUCTOR || name == TRAIT_CONSTRUCTOR
@@ -184,6 +184,11 @@ object NameOps {
184184

185185
def implClassName: N = likeTyped(name ++ tpnme.IMPL_CLASS_SUFFIX)
186186

187+
def freshened(implicit ctx: Context): N =
188+
likeTyped(
189+
if (name.isModuleClassName) name.stripModuleClassSuffix.freshened.moduleClassName
190+
else likeTyped(ctx.freshName(name ++ NameTransformer.NAME_JOIN_STRING)))
191+
187192
/** Translate a name into a list of simple TypeNames and TermNames.
188193
* In all segments before the last, type/term is determined by whether
189194
* the following separator char is '.' or '#'. The last segment

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,18 +254,10 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
254254
} narrowLiftedOwner(caller, liftedOwner(callee.skipConstructor))
255255
} while (changedLiftedOwner)
256256

257-
private def newName(sym: Symbol)(implicit ctx: Context): Name = {
258-
def freshen(prefix: String): Name = {
259-
val fname = ctx.freshName(prefix)
260-
if (sym.isType) fname.toTypeName else fname.toTermName
261-
}
257+
private def newName(sym: Symbol)(implicit ctx: Context): Name =
262258
if (sym.isAnonymousFunction && sym.owner.is(Method, butNot = Label))
263-
freshen(sym.name.toString ++ NJ ++ sym.owner.name ++ NJ)
264-
else if (sym is ModuleClass)
265-
freshen(sym.sourceModule.name.toString ++ NJ).moduleClassName
266-
else
267-
freshen(sym.name.toString ++ NJ)
268-
}
259+
(sym.name ++ NJ ++ sym.owner.name).freshened
260+
else sym.name.freshened
269261

270262
private def generateProxies()(implicit ctx: Context): Unit =
271263
for ((owner, freeValues) <- free.toIterator) {

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,31 +240,34 @@ class Namer { typer: Typer =>
240240

241241
typr.println(i"creating symbol for $tree in ${ctx.mode}")
242242

243-
def checkNoConflict(name: Name): Unit = {
243+
def checkNoConflict(name: Name): Name = {
244+
def errorName(msg: => String) = {
245+
ctx.error(msg, tree.pos)
246+
name.freshened
247+
}
244248
def preExisting = ctx.effectiveScope.lookup(name)
245-
if (ctx.owner is PackageClass) {
249+
if (ctx.owner is PackageClass)
246250
if (preExisting.isDefinedInCurrentRun)
247-
ctx.error(s"${preExisting.showLocated} is compiled twice, runid = ${ctx.runId}", tree.pos)
248-
}
249-
else if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists) {
250-
ctx.error(i"$name is already defined as $preExisting", tree.pos)
251-
}
251+
errorName(s"${preExisting.showLocated} is compiled twice")
252+
else name
253+
else
254+
if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists)
255+
errorName(i"$name is already defined as $preExisting")
256+
else name
252257
}
253258

254259
val inSuperCall = if (ctx.mode is Mode.InSuperCall) InSuperCall else EmptyFlags
255260
tree match {
256261
case tree: TypeDef if tree.isClassDef =>
257-
val name = tree.name.encode.asTypeName
258-
checkNoConflict(name)
262+
val name = checkNoConflict(tree.name.encode).asTypeName
259263
val cls = record(ctx.newClassSymbol(
260264
ctx.owner, name, tree.mods.flags | inSuperCall,
261265
cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree),
262266
privateWithinClass(tree.mods), tree.pos, ctx.source.file))
263267
cls.completer.asInstanceOf[ClassCompleter].init()
264268
cls
265269
case tree: MemberDef =>
266-
val name = tree.name.encode
267-
checkNoConflict(name)
270+
val name = checkNoConflict(tree.name.encode)
268271
val isDeferred = lacksDefinition(tree)
269272
val deferred = if (isDeferred) Deferred else EmptyFlags
270273
val method = if (tree.isInstanceOf[DefDef]) Method else EmptyFlags

test/dotc/tests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class tests extends CompilerTest {
126126
@Test def neg_badAuxConstr = compileFile(negDir, "badAuxConstr", xerrors = 2)
127127
@Test def neg_typetest = compileFile(negDir, "typetest", xerrors = 1)
128128
@Test def neg_t1569_failedAvoid = compileFile(negDir, "t1569-failedAvoid", xerrors = 1)
129+
@Test def neg_clashes = compileFile(negDir, "clashes", xerrors = 2)
129130
@Test def neg_cycles = compileFile(negDir, "cycles", xerrors = 8)
130131
@Test def neg_boundspropagation = compileFile(negDir, "boundspropagation", xerrors = 5)
131132
@Test def neg_refinedSubtyping = compileFile(negDir, "refinedSubtyping", xerrors = 2)
@@ -150,7 +151,6 @@ class tests extends CompilerTest {
150151

151152
@Test def dotty = compileDir(dottyDir, "tools", "-deep" :: "-Ycheck-reentrant" :: allowDeepSubtypes ++ twice) // note the -deep argument
152153

153-
154154
@Test def dotc_ast = compileDir(dotcDir, "ast")
155155
@Test def dotc_config = compileDir(dotcDir, "config")
156156
@Test def dotc_core = compileDir(dotcDir, "core")("-Yno-double-bindings" :: allowDeepSubtypes)// twice omitted to make tests run faster

tests/neg/clashes.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object Test {
2+
class C
3+
type C
4+
}
5+
6+
object Test

0 commit comments

Comments
 (0)