Skip to content

Commit fca2ca4

Browse files
committed
Infer dotted package name for visibility
1 parent e1b4b8d commit fca2ca4

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+28-6
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,17 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
375375
val ctxs = ctx.outersIterator
376376
while !done && ctxs.hasNext do
377377
val cur = ctxs.next()
378-
if cur.owner eq sym then
379-
if importer != null && sym.is(Package) then
380-
done = true // an enclosing package might be imported because p.q not visible as q
381-
else
382-
addCached(cachePoint, Definition)
383-
return // found enclosing definition
378+
if cur.owner.userSymbol eq sym then
379+
if sym.is(Package) then
380+
if cur.isSimplePackage then
381+
precedence = Definition
382+
importer = null
383+
// else package p.q is not available as a simple name but it might be imported
384+
end if
385+
else // found enclosing definition
386+
precedence = Definition
387+
importer = null
388+
done = true
384389
else if isLocal then
385390
if cur.owner eq sym.owner then
386391
done = true // for local def, just checking that it is not enclosing
@@ -966,6 +971,23 @@ object CheckUnused:
966971
inline def userSymbol: Symbol=
967972
if sym.denot.is(ModuleClass) then sym.denot.companionModule else sym
968973

974+
extension (cur: Context)
975+
def isSimplePackage(using Context): Boolean = cur.owner.is(Package) && {
976+
val location = cur.owner.showFullName
977+
val enclosing = cur.outersIterator
978+
.takeWhile(c => !c.owner.isEmptyPackage && !(c.isImportContext && c.importInfo.nn.isRootImport))
979+
.find(c => c.owner.userSymbol ne cur.owner.userSymbol)
980+
enclosing match
981+
case Some(outer) =>
982+
outer.owner.is(Package) // if there is such an outer context, its owner should be package
983+
&& !location
984+
.stripPrefix(outer.owner.showFullName) // p.q in p.q.r
985+
.stripPrefix(".") // leading dot in .r
986+
.contains(".") // remaining r so p.q.v.w leaves v.w
987+
case _ =>
988+
!location.contains(".") // no outer context contributes a name, effectively _root_.p.q
989+
}
990+
969991
extension (sel: ImportSelector)
970992
def boundTpe: Type = sel.bound match
971993
case untpd.TypedSplice(tree) => tree.tpe

tests/warn/i23047.scala

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
package some.example:
44
package demo:
55

6-
import some.example
6+
import some.example // no warn because enclosing package example is not available as a simple name in some
77

88
object Main {
99

@@ -14,6 +14,9 @@ package some.example:
1414

1515
import some.example.demo.Main // warn
1616
println(Main)
17+
18+
import some.example.demo // warn because enclosing package demo is available as a simple name
19+
println(demo.Main)
1720
}
1821
}
1922

0 commit comments

Comments
 (0)