Skip to content

Commit f1151d6

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 7263d25 commit f1151d6

File tree

1 file changed

+29
-21
lines changed

1 file changed

+29
-21
lines changed

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

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -188,32 +188,42 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
188188
/** The type representing a named import with enclosing name when imported
189189
* from given `site` and `selectors`.
190190
*/
191-
def namedImportRef(site: Type, selectors: List[untpd.Tree])(implicit ctx: Context): Type = {
192-
def checkUnambiguous(found: Type) = {
193-
val other = namedImportRef(site, selectors.tail)
194-
if (other.exists && found.exists && (found != other))
195-
error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
196-
tree.pos)
197-
found
198-
}
191+
def namedImportRef(imp: ImportInfo)(implicit ctx: Context): Type = {
199192
val Name = name.toTermName.decode
200-
selectors match {
193+
def recur(selectors: List[untpd.Tree]): Type = selectors match {
201194
case selector :: rest =>
195+
def checkUnambiguous(found: Type) = {
196+
val other = recur(selectors.tail)
197+
if (other.exists && found.exists && (found != other))
198+
error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
199+
tree.pos)
200+
found
201+
}
202+
203+
def selection(name: Name) =
204+
if (imp.sym.isCompleting) {
205+
ctx.warning(i"cyclic ${imp.sym}, ignored", tree.pos)
206+
NoType
207+
}
208+
else {
209+
// Pass refctx so that any errors are reported in the context of the
210+
// reference instead of the
211+
checkUnambiguous(selectionType(imp.site, name, tree.pos)(refctx))
212+
}
213+
202214
selector match {
203215
case Thicket(fromId :: Ident(Name) :: _) =>
204216
val Ident(from) = fromId
205-
val selName = if (name.isTypeName) from.toTypeName else from
206-
// Pass refctx so that any errors are reported in the context of the
207-
// reference instead of the context of the import.
208-
checkUnambiguous(selectionType(site, selName, tree.pos)(refctx))
217+
selection(if (name.isTypeName) from.toTypeName else from)
209218
case Ident(Name) =>
210-
checkUnambiguous(selectionType(site, name, tree.pos)(refctx))
219+
selection(name)
211220
case _ =>
212-
namedImportRef(site, rest)
221+
recur(rest)
213222
}
214223
case nil =>
215224
NoType
216225
}
226+
recur(imp.selectors)
217227
}
218228

219229
/** 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
281291
val curImport = ctx.importInfo
282292
if (ctx.owner.is(Package) && curImport != null && curImport.isRootImport && previous.exists)
283293
previous // no more conflicts possible in this case
284-
else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo) && !curImport.sym.isCompleting) {
285-
val namedImp = namedImportRef(curImport.site, curImport.selectors)
294+
else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo)) {
295+
val namedImp = namedImportRef(curImport)
286296
if (namedImp.exists)
287297
findRef(checkNewOrShadowed(namedImp, namedImport), namedImport, ctx)(outer)
288-
else if (isPossibleImport(wildImport)) {
298+
else if (isPossibleImport(wildImport) && !curImport.sym.isCompleting) {
289299
val wildImp = wildImportRef(curImport)
290300
if (wildImp.exists)
291301
findRef(checkNewOrShadowed(wildImp, wildImport), wildImport, ctx)(outer)
292302
else loop(outer)
293-
}
294-
else loop(outer)
303+
} else loop(outer)
295304
}
296305
else loop(outer)
297306
}
@@ -311,7 +320,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
311320
return typed(desugar.patternVar(tree), pt)
312321
}
313322

314-
315323
val rawType = {
316324
val saved1 = importedFromRoot
317325
val saved2 = foundUnderScala2

0 commit comments

Comments
 (0)