Skip to content

Commit 05fc3cd

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

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

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

+26-5
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,16 @@ 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
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+
done = true
381386
else
382-
addCached(cachePoint, Definition)
383-
return // found enclosing definition
387+
return // found enclosing definition, don't register the reference
384388
else if isLocal then
385389
if cur.owner eq sym.owner then
386390
done = true // for local def, just checking that it is not enclosing
@@ -966,6 +970,23 @@ object CheckUnused:
966970
inline def userSymbol: Symbol=
967971
if sym.denot.is(ModuleClass) then sym.denot.companionModule else sym
968972

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