Skip to content

Commit a4f2671

Browse files
authored
Merge pull request #13593 from dotty-staging/fix-13114
2 parents 2b3f6da + 402d71c commit a4f2671

File tree

12 files changed

+64
-22
lines changed

12 files changed

+64
-22
lines changed

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

+17-4
Original file line numberDiff line numberDiff line change
@@ -153,19 +153,32 @@ class Typer extends Namer
153153
if !suppressErrors then report.error(msg, pos)
154154

155155
/** A symbol qualifies if it really exists and is not a package class.
156-
* In addition, if we are in a constructor of a pattern, we ignore all definitions
157-
* which are methods and not accessors (note: if we don't do that
158-
* case x :: xs in class List would return the :: method).
159-
*
160156
* Package classes are part of their parent's scope, because otherwise
161157
* we could not reload them via `_.member`. On the other hand, accessing a
162158
* package as a type from source is always an error.
159+
160+
* In addition:
161+
* - if we are in a constructor of a pattern, we ignore all definitions
162+
* which are methods and not accessors (note: if we don't do that
163+
* case x :: xs in class List would return the :: method).
164+
* - Members of the empty package can be accessed only from within the empty package.
165+
* Note: it would be cleaner to never nest package definitions in empty package definitions,
166+
* but then we'd have to give up the fiction that a compilation unit consists of
167+
* a single tree (because a source file may have both toplevel classes which go
168+
* into the empty package and package definitions, which would have to stay outside).
169+
* Since the principle of a single tree per compilation unit is assumed by many
170+
* tools, we did not want to take that step.
163171
*/
164172
def qualifies(denot: Denotation): Boolean =
165173
reallyExists(denot)
166174
&& (!pt.isInstanceOf[UnapplySelectionProto]
167175
|| denot.hasAltWith(sd => !sd.symbol.is(Method, butNot = Accessor)))
168176
&& !denot.symbol.is(PackageClass)
177+
&& {
178+
var owner = denot.symbol.maybeOwner
179+
if owner.isPackageObject then owner = owner.owner
180+
!owner.isEmptyPackage || ctx.owner.enclosingPackageClass.isEmptyPackage
181+
}
169182

170183
/** Find the denotation of enclosing `name` in given context `ctx`.
171184
* @param previous A denotation that was found in a more deeply nested scope,

language-server/test/dotty/tools/languageserver/CompletionTest.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,8 @@ class CompletionTest {
547547
}
548548

549549
@Test def completeFromPackageObjectWithInheritance: Unit = {
550-
code"""trait Foo[A] { def xxxx(a: A) = a }
550+
code"""package test
551+
|trait Foo[A] { def xxxx(a: A) = a }
551552
|package object foo extends Foo[Int] {}
552553
|object Test {
553554
| foo.xx$m1

tests/neg/i13114/A.scala

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def f = 42
2+
3+
class C

tests/neg/i13114/B.scala

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class D2 extends C
2+
3+
package p {
4+
class D extends C // error: not found
5+
6+
@main def test = println(new D)
7+
}

tests/neg/i7891.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// was previously ok in one compilation unit
2+
def f22 = "hello, world"
3+
4+
package p {
5+
@main def m = println(f22) // error
6+
}

tests/neg/implicit-package-object.scala

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
trait ToString[A] {
2-
def print(a: A): Unit
3-
}
1+
package toString:
2+
trait ToString[A] {
3+
def print(a: A): Unit
4+
}
5+
6+
import toString._
47

58
package A {
69
case class AA(text: String)

tests/pos/i0239.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
package i0239
2+
13
package p {
24
class C[A] {
35
implicit def foo: M[A] = ???

tests/pos/i5978.scala

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
package test
12
import scala.language.implicitConversions
23

34
opaque type Position[Buffer] = Int

tests/pos/pos_valueclasses/t5953.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
package t5953
2+
13
trait CBF[-F, -A, +C]
24
trait GenTraversable[+A]
35
trait Traversable[+A] extends GenTraversable[A]

tests/run-staging/i4730.scala

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
import scala.quoted.*
22
import scala.quoted.staging.*
33

4-
object Test {
4+
5+
package i4730:
56
given Compiler = Compiler.make(getClass.getClassLoader)
67
def ret(using Quotes): Expr[Int => Int] = '{ (x: Int) =>
78
${
89
val z = run('{x + 1}) // throws scala.quoted.runtime.impl.ScopeException =>
910
Expr(z)
1011
}
1112
}
12-
def main(args: Array[String]): Unit = {
13-
scala.mytest.myTest()
14-
}
15-
}
1613

1714
package scala {
1815
package mytest {
1916
def myTest()(using Compiler) = {
2017
try {
21-
run(Test.ret).apply(10)
18+
run(i4730.ret).apply(10)
2219
throw new Exception
2320
} catch {
2421
case ex: Exception if ex.getClass.getName == "scala.quoted.runtime.impl.ScopeException" =>
@@ -27,3 +24,9 @@ package scala {
2724
}
2825
}
2926
}
27+
object Test {
28+
import i4730.given
29+
def main(args: Array[String]): Unit = {
30+
scala.mytest.myTest()
31+
}
32+
}

tests/run-staging/i6992/Macro_1.scala

+8-7
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22
import scala.quoted.*
33
import scala.quoted.staging.*
44

5+
package macros:
56

6-
object macros {
7-
inline def mcr(x: => Any): Any = ${mcrImpl('x)}
7+
object macros {
8+
inline def mcr(x: => Any): Any = ${mcrImpl('x)}
89

9-
class Foo { val x = 10 }
10+
class Foo { val x = 10 }
1011

11-
def mcrImpl(body: Expr[Any])(using ctx: Quotes): Expr[Any] =
12-
MyTest.mcrImpl(body)
13-
}
12+
def mcrImpl(body: Expr[Any])(using ctx: Quotes): Expr[Any] =
13+
MyTest.mcrImpl(body)
14+
}
1415

1516
package scala {
1617
object MyTest {
17-
import macros.*
18+
import macros.macros.*
1819

1920
given Compiler = Compiler.make(getClass.getClassLoader)
2021

tests/run-staging/i6992/Test_2.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import macros.*
1+
import macros.macros.*
22

33
object Test {
44
val foo = new Foo

0 commit comments

Comments
 (0)