diff options
author | Martin Odersky <odersky@gmail.com> | 2016-11-09 12:33:14 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-12-01 13:55:12 +0100 |
commit | f1151d658ade02d6e838ab11d9d9700a89762558 (patch) | |
tree | 2722eebdfac6cab36aaecab233359f24fa3affe0 /compiler/src/dotty/tools/dotc/typer/Typer.scala | |
parent | 7263d25b463423677c9e632088b813fadce464ba (diff) | |
download | dotty-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.scala | 50 |
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 |