@@ -12,7 +12,7 @@ import config.Printers.{implicits, implicitsDetailed}
1212import ast .{untpd , tpd }
1313import Implicits .{hasExtMethod , Candidate }
1414import java .util .{Timer , TimerTask }
15- import collection .mutable
15+ import collection .mutable , mutable . ListBuffer
1616import scala .util .control .NonFatal
1717import cc .isCaptureChecking
1818
@@ -57,7 +57,7 @@ trait ImportSuggestions:
5757 * skipped as an optimization, since they won't contain implicits anyway.
5858 */
5959 private def suggestionRoots (using Context ) =
60- val seen = mutable.Set [TermRef ]()
60+ val seen = mutable.Set .empty [TermRef ]
6161
6262 def lookInside (root : Symbol )(using Context ): Boolean =
6363 explore {
@@ -70,7 +70,7 @@ trait ImportSuggestions:
7070 }
7171
7272 def nestedRoots (site : Type )(using Context ): List [Symbol ] =
73- val seenNames = mutable.Set [Name ]()
73+ val seenNames = mutable.Set .empty [Name ]
7474 site.baseClasses.flatMap { bc =>
7575 bc.info.decls.filter { dcl =>
7676 lookInside(dcl)
@@ -275,7 +275,7 @@ trait ImportSuggestions:
275275 * have the same String part. Elements are sorted by their String parts.
276276 */
277277 extension (refs : List [(TermRef , String )]) def distinctRefs (using Context ): List [TermRef ] =
278- val buf = new mutable. ListBuffer [TermRef ]
278+ val buf = ListBuffer .empty [TermRef ]
279279 var last = " "
280280 for (ref, str) <- refs do
281281 if last != str then
@@ -290,7 +290,7 @@ trait ImportSuggestions:
290290 extension (refs : List [TermRef ]) def best (n : Int )(using Context ): List [TermRef ] =
291291 val top = new Array [TermRef ](n)
292292 var filled = 0
293- val rest = new mutable. ListBuffer [TermRef ]
293+ val rest = ListBuffer .empty [TermRef ]
294294 val noImplicitsCtx = ctx.retractMode(Mode .ImplicitsEnabled )
295295 for ref <- refs do
296296 var i = 0
@@ -335,15 +335,33 @@ trait ImportSuggestions:
335335 else
336336 ctx.printer.toTextRef(ref).show
337337 s " import $imported"
338- val suggestions = suggestedRefs
338+ def indubitably (ref : TermRef ): Boolean =
339+ ref.symbol.isAccessibleFrom(ctx.owner.info)
340+ val (suggested, dubious) = suggestedRefs
339341 .zip(suggestedRefs.map(importString))
340342 .filter((ref, str) => str.contains('.' )) // must be a real import with `.`
341343 .sortBy(_._2) // sort first alphabetically for stability
342344 .distinctRefs // TermRefs might be different but generate the same strings
343345 .best(MaxSuggestions ) // take MaxSuggestions best references according to specificity
344- .map(importString)
345- if suggestions.isEmpty then " "
346+ .partition(indubitably)
347+ if suggested.isEmpty then
348+ if dubious.isEmpty then " "
349+ else
350+ def isImportable (ref : TermRef ): Boolean =
351+ ctx.outersIterator.exists(outer => outer.isImportContext && ! outer.importInfo.nn.isRootImport
352+ && outer.importInfo.nn.site =:= ref.prefix
353+ && outer.importInfo.nn.selectors.exists(sel => sel.isWildcard || sel.name == ref.name))
354+ def dubiousAdvice (ref : TermRef ): String =
355+ s " ${importString(ref)}${if isImportable(ref) then " // existing imported member is not accessible" else " " }"
356+ i """
357+ |
358+ |Consider making one of the following imports accessible to $help:
359+ |
360+ | ${dubious.map(dubiousAdvice)}%\n%
361+ |
362+ | """
346363 else
364+ val suggestions = suggested.map(importString)
347365 val fix =
348366 if suggestions.tail.isEmpty then " The following import"
349367 else " One of the following imports"
0 commit comments