Skip to content

Commit d87bbb1

Browse files
authored
Enclosing package p.q not visible as q (#23069)
Fixes #23047 Normally, an enclosing definition always has higher "name binding" precedence than an import, but an enclosing packaging can have a dotted name with a simple name that can't be referenced without qualification or import.
2 parents 5ac8a32 + e392382 commit d87bbb1

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

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

+7-6
Original file line numberDiff line numberDiff line change
@@ -370,15 +370,15 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
370370
var cachePoint: Context = NoContext // last context with Resolved cache
371371
var importer: ImportSelector | Null = null // non-null for import context
372372
var precedence = NoPrecedence // of current resolution
373+
var enclosed = false // true if sym is owner of an enclosing context
373374
var done = false
374375
var cached = false
375376
val ctxs = ctx.outersIterator
376377
while !done && ctxs.hasNext do
377378
val cur = ctxs.next()
378-
if cur.owner eq sym then
379-
addCached(cachePoint, Definition)
380-
return // found enclosing definition
381-
else if isLocal then
379+
if cur.owner.userSymbol == sym && !sym.is(Package) then
380+
enclosed = true // found enclosing definition, don't register the reference
381+
if isLocal then
382382
if cur.owner eq sym.owner then
383383
done = true // for local def, just checking that it is not enclosing
384384
else
@@ -419,7 +419,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
419419
candidate = cur
420420
importer = sel
421421
else if checkMember(cur.owner) then
422-
if sym.srcPos.sourcePos.source == ctx.source then
422+
if sym.is(Package) || sym.srcPos.sourcePos.source == ctx.source then
423423
precedence = Definition
424424
candidate = cur
425425
importer = null // ignore import in same scope; we can't check nesting level
@@ -429,7 +429,8 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
429429
candidate = cur
430430
end while
431431
// record usage and possibly an import
432-
refInfos.refs.addOne(sym)
432+
if !enclosed then
433+
refInfos.refs.addOne(sym)
433434
if candidate != NoContext && candidate.isImportContext && importer != null then
434435
refInfos.sels.put(importer, ())
435436
// possibly record that we have performed this look-up

tests/warn/i23047.scala

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//> using options -Wunused:imports
2+
3+
package some.example:
4+
package demo:
5+
6+
import some.example // no warn because enclosing package example is not available as a simple name in some
7+
8+
object Main {
9+
10+
def generic[T](x: Any): T = null.asInstanceOf[T]
11+
12+
def main(args: Array[String]): Unit = {
13+
generic[example.Util](0)
14+
15+
import some.example.demo.Main // warn
16+
println(Main)
17+
18+
import some.example.demo // warn because enclosing package demo is available as a simple name
19+
println(demo.Main)
20+
}
21+
}
22+
23+
package some.example:
24+
25+
class Util

0 commit comments

Comments
 (0)