aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2016-11-17 17:17:38 +0100
committerGitHub <noreply@github.com>2016-11-17 17:17:38 +0100
commitdd0db48342b3ccc773373870f36348de846c66e4 (patch)
treef570ca1d762dc7d04ad61d808ae7bd5ca19454c9
parent156a9d978c9dab8e63ce1677a8743487057533ba (diff)
parent040379e2d5a77722563d73723044e065f2c1632b (diff)
downloaddotty-dd0db48342b3ccc773373870f36348de846c66e4.tar.gz
dotty-dd0db48342b3ccc773373870f36348de846c66e4.tar.bz2
dotty-dd0db48342b3ccc773373870f36348de846c66e4.zip
Merge pull request #1722 from dotty-staging/topic/fix#1708
Fix #1708: duplicate symbols in package
-rw-r--r--src/dotty/tools/dotc/reporting/diagnostic/messages.scala10
-rw-r--r--src/dotty/tools/dotc/typer/FrontEnd.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala21
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala21
-rw-r--r--tests/neg/i1708.scala2
-rw-r--r--tests/neg/i1708b.scala10
6 files changed, 51 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index 446c0e0c7..489165e56 100644
--- a/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -790,7 +790,8 @@ object messages {
val explanation = ""
}
- case class SeqWildcardPatternPos()(implicit ctx: Context) extends Message(31) {
+ case class SeqWildcardPatternPos()(implicit ctx: Context)
+ extends Message(31) {
val kind = "Syntax"
val msg = "`_*' can be used only for last argument"
val explanation = {
@@ -891,4 +892,11 @@ object messages {
|"""
}
}
+
+ case class PkgDuplicateSymbol(existing: Symbol)(implicit ctx: Context)
+ extends Message(33) {
+ val kind = "Duplicate Symbol"
+ val msg = hl"trying to define package with same name as `$existing`"
+ val explanation = ""
+ }
}
diff --git a/src/dotty/tools/dotc/typer/FrontEnd.scala b/src/dotty/tools/dotc/typer/FrontEnd.scala
index 4ce24b633..7bbf0169b 100644
--- a/src/dotty/tools/dotc/typer/FrontEnd.scala
+++ b/src/dotty/tools/dotc/typer/FrontEnd.scala
@@ -35,7 +35,7 @@ class FrontEnd extends Phase {
else new Parser(unit.source).parse()
val printer = if (ctx.settings.Xprint.value.contains("parser")) default else typr
printer.println("parsed:\n" + unit.untpdTree.show)
- if (Config.checkPositions)
+ if (Config.checkPositions)
unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors)
}
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 687de1e7a..78f0da1f0 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -21,6 +21,7 @@ import Inferencing._
import transform.ValueClasses._
import TypeApplications._
import language.implicitConversions
+import reporting.diagnostic.messages._
trait NamerContextOps { this: Context =>
@@ -264,7 +265,7 @@ class Namer { typer: Typer =>
def preExisting = ctx.effectiveScope.lookup(name)
if (ctx.owner is PackageClass)
if (preExisting.isDefinedInCurrentRun)
- errorName(s"${preExisting.showLocated} is compiled twice")
+ errorName(s"${preExisting.showLocated} has already been compiled\nonce during this run")
else name
else
if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists)
@@ -343,8 +344,17 @@ class Namer { typer: Typer =>
case Select(qual: RefTree, _) => createPackageSymbol(qual).moduleClass
}
val existing = pkgOwner.info.decls.lookup(pid.name)
+
if ((existing is Package) && (pkgOwner eq existing.owner)) existing
- else ctx.newCompletePackageSymbol(pkgOwner, pid.name.asTermName).entered
+ else {
+ /** If there's already an existing type, then the package is a dup of this type */
+ val existingType = pkgOwner.info.decls.lookup(pid.name.toTypeName)
+ if (existingType.exists) {
+ ctx.error(PkgDuplicateSymbol(existingType), pid.pos)
+ ctx.newCompletePackageSymbol(pkgOwner, (pid.name ++ "$_error_").toTermName).entered
+ }
+ else ctx.newCompletePackageSymbol(pkgOwner, pid.name.asTermName).entered
+ }
}
/** Expand tree and store in `expandedTree` */
@@ -377,9 +387,10 @@ class Namer { typer: Typer =>
localCtx
}
- /** For all class definitions `stat` in `xstats`: If the companion class if not also defined
- * in `xstats`, invalidate it by setting its info to NoType.
- */
+ /** For all class definitions `stat` in `xstats`: If the companion class if
+ * not also defined in `xstats`, invalidate it by setting its info to
+ * NoType.
+ */
def invalidateCompanions(pkg: Symbol, xstats: List[untpd.Tree])(implicit ctx: Context): Unit = {
val definedNames = xstats collect { case stat: NameTree => stat.name }
def invalidate(name: TypeName) =
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 667e1f82e..0ee9a2799 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -1341,14 +1341,19 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedPackageDef(tree: untpd.PackageDef)(implicit ctx: Context): Tree = track("typedPackageDef") {
val pid1 = typedExpr(tree.pid, AnySelectionProto)(ctx.addMode(Mode.InPackageClauseName))
val pkg = pid1.symbol
- val packageContext =
- if (pkg is Package) ctx.fresh.setOwner(pkg.moduleClass).setTree(tree)
- else {
- ctx.error(em"$pkg is already defined, cannot be a package", tree.pos)
- ctx
- }
- val stats1 = typedStats(tree.stats, pkg.moduleClass)(packageContext)
- cpy.PackageDef(tree)(pid1.asInstanceOf[RefTree], stats1) withType pkg.valRef
+
+ // Package will not exist if a duplicate type has already been entered, see
+ // `tests/neg/1708.scala`, else branch's error message should be supressed
+ if (pkg.exists) {
+ val packageContext =
+ if (pkg is Package) ctx.fresh.setOwner(pkg.moduleClass).setTree(tree)
+ else {
+ ctx.error(em"$pkg is already defined, cannot be a package", tree.pos)
+ ctx
+ }
+ val stats1 = typedStats(tree.stats, pkg.moduleClass)(packageContext)
+ cpy.PackageDef(tree)(pid1.asInstanceOf[RefTree], stats1) withType pkg.valRef
+ } else errorTree(tree, i"package ${tree.pid.name} does not exist")
}
def typedAnnotated(tree: untpd.Annotated, pt: Type)(implicit ctx: Context): Tree = track("typedAnnotated") {
diff --git a/tests/neg/i1708.scala b/tests/neg/i1708.scala
new file mode 100644
index 000000000..47bc456f3
--- /dev/null
+++ b/tests/neg/i1708.scala
@@ -0,0 +1,2 @@
+package foo { trait identifier }
+package foo { class identifier } // error
diff --git a/tests/neg/i1708b.scala b/tests/neg/i1708b.scala
new file mode 100644
index 000000000..9bcf1864d
--- /dev/null
+++ b/tests/neg/i1708b.scala
@@ -0,0 +1,10 @@
+package foo {
+ trait id {
+ def bar: Int
+ }
+}
+package foo {
+ package id { // error
+ class Bar
+ }
+}