diff options
author | Dmitry Petrashko <dark@d-d.me> | 2015-07-20 11:48:42 +0200 |
---|---|---|
committer | Dmitry Petrashko <dark@d-d.me> | 2015-07-20 11:48:42 +0200 |
commit | d07e5d1ea36e4457c3491711bc65251d4a5290b9 (patch) | |
tree | cadd7758135b15906b005dee41d5dc09882ea56e | |
parent | 1f45c67773c0910dd51563f61e4c8b57ac7d8e85 (diff) | |
parent | 5feab112fb7d5a5c8ae1de1bbb2ad9e430b1f452 (diff) | |
download | dotty-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.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/LambdaLift.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 25 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/neg/clashes.scala | 6 |
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 |