Skip to content

Avoid crashes on double definitions #719

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
14 changes: 3 additions & 11 deletions src/dotty/tools/dotc/transform/LambdaLift.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
25 changes: 14 additions & 11 deletions src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -240,31 +240,34 @@ 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),
privateWithinClass(tree.mods), tree.pos, ctx.source.file))
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
Expand Down
2 changes: 1 addition & 1 deletion test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -148,7 +149,6 @@ class tests extends CompilerTest {

@Test def dotty = compileDir(dottyDir, "tools", "-deep" :: 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
Expand Down
6 changes: 6 additions & 0 deletions tests/neg/clashes.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object Test {
class C
type C
}

object Test