aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/typer/Typer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-11-09 12:33:14 +0100
committerMartin Odersky <odersky@gmail.com>2016-12-01 13:55:12 +0100
commitf1151d658ade02d6e838ab11d9d9700a89762558 (patch)
tree2722eebdfac6cab36aaecab233359f24fa3affe0 /compiler/src/dotty/tools/dotc/typer/Typer.scala
parent7263d25b463423677c9e632088b813fadce464ba (diff)
downloaddotty-f1151d658ade02d6e838ab11d9d9700a89762558.tar.gz
dotty-f1151d658ade02d6e838ab11d9d9700a89762558.tar.bz2
dotty-f1151d658ade02d6e838ab11d9d9700a89762558.zip
Be more lazy in namedImportRef
We got a hard to track down error when changing to the new annotations elaboration scheme (should be in the next commit): When running `testNonCyclic`, `DotClass` was not found in object Trees even though it was imported from `util`. It turned out that the import was ignored because the `util` symbol was completing. This commit adds a warning when this happens. The warning currently applies only to named imports because several false negatives were encountered if we do this also on wildcard imports. I.e. we get a warning, but the searched after symbol is not a member of the wildcard qualifier. This commit also refactors namedImportRef, so that `site` is only computed when the name to reseolve appears in the selector list. That change made the previously observed error go away because less is now forced.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala50
1 files changed, 29 insertions, 21 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index ccc74cfff..6c876858b 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -188,32 +188,42 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
/** The type representing a named import with enclosing name when imported
* from given `site` and `selectors`.
*/
- def namedImportRef(site: Type, selectors: List[untpd.Tree])(implicit ctx: Context): Type = {
- def checkUnambiguous(found: Type) = {
- val other = namedImportRef(site, selectors.tail)
- if (other.exists && found.exists && (found != other))
- error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
- tree.pos)
- found
- }
+ def namedImportRef(imp: ImportInfo)(implicit ctx: Context): Type = {
val Name = name.toTermName.decode
- selectors match {
+ def recur(selectors: List[untpd.Tree]): Type = selectors match {
case selector :: rest =>
+ def checkUnambiguous(found: Type) = {
+ val other = recur(selectors.tail)
+ if (other.exists && found.exists && (found != other))
+ error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
+ tree.pos)
+ found
+ }
+
+ def selection(name: Name) =
+ if (imp.sym.isCompleting) {
+ ctx.warning(i"cyclic ${imp.sym}, ignored", tree.pos)
+ NoType
+ }
+ else {
+ // Pass refctx so that any errors are reported in the context of the
+ // reference instead of the
+ checkUnambiguous(selectionType(imp.site, name, tree.pos)(refctx))
+ }
+
selector match {
case Thicket(fromId :: Ident(Name) :: _) =>
val Ident(from) = fromId
- val selName = if (name.isTypeName) from.toTypeName else from
- // Pass refctx so that any errors are reported in the context of the
- // reference instead of the context of the import.
- checkUnambiguous(selectionType(site, selName, tree.pos)(refctx))
+ selection(if (name.isTypeName) from.toTypeName else from)
case Ident(Name) =>
- checkUnambiguous(selectionType(site, name, tree.pos)(refctx))
+ selection(name)
case _ =>
- namedImportRef(site, rest)
+ recur(rest)
}
case nil =>
NoType
}
+ recur(imp.selectors)
}
/** The type representing a wildcard import with enclosing name when imported
@@ -281,17 +291,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val curImport = ctx.importInfo
if (ctx.owner.is(Package) && curImport != null && curImport.isRootImport && previous.exists)
previous // no more conflicts possible in this case
- else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo) && !curImport.sym.isCompleting) {
- val namedImp = namedImportRef(curImport.site, curImport.selectors)
+ else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo)) {
+ val namedImp = namedImportRef(curImport)
if (namedImp.exists)
findRef(checkNewOrShadowed(namedImp, namedImport), namedImport, ctx)(outer)
- else if (isPossibleImport(wildImport)) {
+ else if (isPossibleImport(wildImport) && !curImport.sym.isCompleting) {
val wildImp = wildImportRef(curImport)
if (wildImp.exists)
findRef(checkNewOrShadowed(wildImp, wildImport), wildImport, ctx)(outer)
else loop(outer)
- }
- else loop(outer)
+ } else loop(outer)
}
else loop(outer)
}
@@ -311,7 +320,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
return typed(desugar.patternVar(tree), pt)
}
-
val rawType = {
val saved1 = importedFromRoot
val saved2 = foundUnderScala2