diff options
author | odersky <odersky@gmail.com> | 2016-11-17 17:17:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-17 17:17:38 +0100 |
commit | dd0db48342b3ccc773373870f36348de846c66e4 (patch) | |
tree | f570ca1d762dc7d04ad61d808ae7bd5ca19454c9 | |
parent | 156a9d978c9dab8e63ce1677a8743487057533ba (diff) | |
parent | 040379e2d5a77722563d73723044e065f2c1632b (diff) | |
download | dotty-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.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/FrontEnd.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 21 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 21 | ||||
-rw-r--r-- | tests/neg/i1708.scala | 2 | ||||
-rw-r--r-- | tests/neg/i1708b.scala | 10 |
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 + } +} |