aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2015-07-20 11:48:42 +0200
committerDmitry Petrashko <dark@d-d.me>2015-07-20 11:48:42 +0200
commitd07e5d1ea36e4457c3491711bc65251d4a5290b9 (patch)
treecadd7758135b15906b005dee41d5dc09882ea56e
parent1f45c67773c0910dd51563f61e4c8b57ac7d8e85 (diff)
parent5feab112fb7d5a5c8ae1de1bbb2ad9e430b1f452 (diff)
downloaddotty-d07e5d1ea36e4457c3491711bc65251d4a5290b9.tar.gz
dotty-d07e5d1ea36e4457c3491711bc65251d4a5290b9.tar.bz2
dotty-d07e5d1ea36e4457c3491711bc65251d4a5290b9.zip
Merge pull request #719 from dotty-staging/fix/doubledefs
Avoid crashes on double definitions
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala9
-rw-r--r--src/dotty/tools/dotc/transform/LambdaLift.scala14
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala25
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/neg/clashes.scala6
5 files changed, 31 insertions, 25 deletions
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index 4d6cca61d..dc90a8d3b 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -6,7 +6,7 @@ import scala.annotation.switch
import scala.io.Codec
import Names._, StdNames._, Contexts._, Symbols._, Flags._
import Decorators.StringDecorator
-import dotty.tools.dotc.util.Chars
+import util.{Chars, NameTransformer}
import Chars.isOperatorPart
object NameOps {
@@ -59,7 +59,7 @@ object NameOps {
implicit class NameDecorator[N <: Name](val name: N) extends AnyVal {
import nme._
- def likeTyped(n: Name): N =
+ def likeTyped(n: PreName): N =
(if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N]
def isConstructorName = name == CONSTRUCTOR || name == TRAIT_CONSTRUCTOR
@@ -184,6 +184,11 @@ object NameOps {
def implClassName: N = likeTyped(name ++ tpnme.IMPL_CLASS_SUFFIX)
+ def freshened(implicit ctx: Context): N =
+ likeTyped(
+ if (name.isModuleClassName) name.stripModuleClassSuffix.freshened.moduleClassName
+ else likeTyped(ctx.freshName(name ++ NameTransformer.NAME_JOIN_STRING)))
+
/** Translate a name into a list of simple TypeNames and TermNames.
* In all segments before the last, type/term is determined by whether
* the following separator char is '.' or '#'. The last segment
diff --git a/src/dotty/tools/dotc/transform/LambdaLift.scala b/src/dotty/tools/dotc/transform/LambdaLift.scala
index cefd283be..19ad06085 100644
--- a/src/dotty/tools/dotc/transform/LambdaLift.scala
+++ b/src/dotty/tools/dotc/transform/LambdaLift.scala
@@ -254,18 +254,10 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
} narrowLiftedOwner(caller, liftedOwner(callee.skipConstructor))
} while (changedLiftedOwner)
- private def newName(sym: Symbol)(implicit ctx: Context): Name = {
- def freshen(prefix: String): Name = {
- val fname = ctx.freshName(prefix)
- if (sym.isType) fname.toTypeName else fname.toTermName
- }
+ private def newName(sym: Symbol)(implicit ctx: Context): Name =
if (sym.isAnonymousFunction && sym.owner.is(Method, butNot = Label))
- freshen(sym.name.toString ++ NJ ++ sym.owner.name ++ NJ)
- else if (sym is ModuleClass)
- freshen(sym.sourceModule.name.toString ++ NJ).moduleClassName
- else
- freshen(sym.name.toString ++ NJ)
- }
+ (sym.name ++ NJ ++ sym.owner.name).freshened
+ else sym.name.freshened
private def generateProxies()(implicit ctx: Context): Unit =
for ((owner, freeValues) <- free.toIterator) {
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index cdce11f22..f6a0c8cc3 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -240,22 +240,26 @@ class Namer { typer: Typer =>
typr.println(i"creating symbol for $tree in ${ctx.mode}")
- def checkNoConflict(name: Name): Unit = {
+ def checkNoConflict(name: Name): Name = {
+ def errorName(msg: => String) = {
+ ctx.error(msg, tree.pos)
+ name.freshened
+ }
def preExisting = ctx.effectiveScope.lookup(name)
- if (ctx.owner is PackageClass) {
+ if (ctx.owner is PackageClass)
if (preExisting.isDefinedInCurrentRun)
- ctx.error(s"${preExisting.showLocated} is compiled twice, runid = ${ctx.runId}", tree.pos)
- }
- else if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists) {
- ctx.error(i"$name is already defined as $preExisting", tree.pos)
- }
+ errorName(s"${preExisting.showLocated} is compiled twice")
+ else name
+ else
+ if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists)
+ errorName(i"$name is already defined as $preExisting")
+ else name
}
val inSuperCall = if (ctx.mode is Mode.InSuperCall) InSuperCall else EmptyFlags
tree match {
case tree: TypeDef if tree.isClassDef =>
- val name = tree.name.encode.asTypeName
- checkNoConflict(name)
+ val name = checkNoConflict(tree.name.encode).asTypeName
val cls = record(ctx.newClassSymbol(
ctx.owner, name, tree.mods.flags | inSuperCall,
cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree),
@@ -263,8 +267,7 @@ class Namer { typer: Typer =>
cls.completer.asInstanceOf[ClassCompleter].init()
cls
case tree: MemberDef =>
- val name = tree.name.encode
- checkNoConflict(name)
+ val name = checkNoConflict(tree.name.encode)
val isDeferred = lacksDefinition(tree)
val deferred = if (isDeferred) Deferred else EmptyFlags
val method = if (tree.isInstanceOf[DefDef]) Method else EmptyFlags
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index fbf26044c..838b4dbb3 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -126,6 +126,7 @@ class tests extends CompilerTest {
@Test def neg_badAuxConstr = compileFile(negDir, "badAuxConstr", xerrors = 2)
@Test def neg_typetest = compileFile(negDir, "typetest", xerrors = 1)
@Test def neg_t1569_failedAvoid = compileFile(negDir, "t1569-failedAvoid", xerrors = 1)
+ @Test def neg_clashes = compileFile(negDir, "clashes", xerrors = 2)
@Test def neg_cycles = compileFile(negDir, "cycles", xerrors = 8)
@Test def neg_boundspropagation = compileFile(negDir, "boundspropagation", xerrors = 5)
@Test def neg_refinedSubtyping = compileFile(negDir, "refinedSubtyping", xerrors = 2)
@@ -150,7 +151,6 @@ class tests extends CompilerTest {
@Test def dotty = compileDir(dottyDir, "tools", "-deep" :: "-Ycheck-reentrant" :: allowDeepSubtypes ++ twice) // note the -deep argument
-
@Test def dotc_ast = compileDir(dotcDir, "ast")
@Test def dotc_config = compileDir(dotcDir, "config")
@Test def dotc_core = compileDir(dotcDir, "core")("-Yno-double-bindings" :: allowDeepSubtypes)// twice omitted to make tests run faster
diff --git a/tests/neg/clashes.scala b/tests/neg/clashes.scala
new file mode 100644
index 000000000..11354706d
--- /dev/null
+++ b/tests/neg/clashes.scala
@@ -0,0 +1,6 @@
+object Test {
+ class C
+ type C
+}
+
+object Test