Skip to content

Commit 9ddeb13

Browse files
committed
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.
1 parent 6e2c6e0 commit 9ddeb13

File tree

1 file changed

+29
-21
lines changed

1 file changed

+29
-21
lines changed

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -183,32 +183,42 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
183183
/** The type representing a named import with enclosing name when imported
184184
* from given `site` and `selectors`.
185185
*/
186-
def namedImportRef(site: Type, selectors: List[untpd.Tree])(implicit ctx: Context): Type = {
187-
def checkUnambiguous(found: Type) = {
188-
val other = namedImportRef(site, selectors.tail)
189-
if (other.exists && found.exists && (found != other))
190-
error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
191-
tree.pos)
192-
found
193-
}
186+
def namedImportRef(imp: ImportInfo)(implicit ctx: Context): Type = {
194187
val Name = name.toTermName.decode
195-
selectors match {
188+
def recur(selectors: List[untpd.Tree]): Type = selectors match {
196189
case selector :: rest =>
190+
def checkUnambiguous(found: Type) = {
191+
val other = recur(selectors.tail)
192+
if (other.exists && found.exists && (found != other))
193+
error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
194+
tree.pos)
195+
found
196+
}
197+
198+
def selection(name: Name) =
199+
if (imp.sym.isCompleting) {
200+
ctx.warning(i"cyclic ${imp.sym}, ignored", tree.pos)
201+
NoType
202+
}
203+
else {
204+
// Pass refctx so that any errors are reported in the context of the
205+
// reference instead of the
206+
checkUnambiguous(selectionType(imp.site, name, tree.pos)(refctx))
207+
}
208+
197209
selector match {
198210
case Thicket(fromId :: Ident(Name) :: _) =>
199211
val Ident(from) = fromId
200-
val selName = if (name.isTypeName) from.toTypeName else from
201-
// Pass refctx so that any errors are reported in the context of the
202-
// reference instead of the context of the import.
203-
checkUnambiguous(selectionType(site, selName, tree.pos)(refctx))
212+
selection(if (name.isTypeName) from.toTypeName else from)
204213
case Ident(Name) =>
205-
checkUnambiguous(selectionType(site, name, tree.pos)(refctx))
214+
selection(name)
206215
case _ =>
207-
namedImportRef(site, rest)
216+
recur(rest)
208217
}
209218
case nil =>
210219
NoType
211220
}
221+
recur(imp.selectors)
212222
}
213223

214224
/** The type representing a wildcard import with enclosing name when imported
@@ -276,17 +286,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
276286
val curImport = ctx.importInfo
277287
if (ctx.owner.is(Package) && curImport != null && curImport.isRootImport && previous.exists)
278288
previous // no more conflicts possible in this case
279-
else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo) && !curImport.sym.isCompleting) {
280-
val namedImp = namedImportRef(curImport.site, curImport.selectors)
289+
else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo)) {
290+
val namedImp = namedImportRef(curImport)
281291
if (namedImp.exists)
282292
findRef(checkNewOrShadowed(namedImp, namedImport), namedImport, ctx)(outer)
283-
else if (isPossibleImport(wildImport)) {
293+
else if (isPossibleImport(wildImport) && !curImport.sym.isCompleting) {
284294
val wildImp = wildImportRef(curImport)
285295
if (wildImp.exists)
286296
findRef(checkNewOrShadowed(wildImp, wildImport), wildImport, ctx)(outer)
287297
else loop(outer)
288-
}
289-
else loop(outer)
298+
} else loop(outer)
290299
}
291300
else loop(outer)
292301
}
@@ -306,7 +315,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
306315
return typed(desugar.patternVar(tree), pt)
307316
}
308317

309-
310318
val rawType = {
311319
val saved1 = importedFromRoot
312320
val saved2 = foundUnderScala2

0 commit comments

Comments
 (0)