Skip to content

Commit

Permalink
Explain accessible scope of private members in error message
Browse files Browse the repository at this point in the history
Fixes #18686
  • Loading branch information
nicolasstucki committed Oct 13, 2023
1 parent 8aec15b commit 899dc46
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 26 deletions.
18 changes: 12 additions & 6 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2987,12 +2987,18 @@ extends ReferenceMsg(CannotBeAccessedID):
val where = if (ctx.owner.exists) i" from ${ctx.owner.enclosingClass}" else ""
val whyNot = new StringBuffer
for alt <- alts do
if alt.is(Protected) then
val cls = alt.owner.enclosingSubClass
val owner = if cls.exists then cls else alt.owner
val location = if owner.is(Final) then owner.showLocated else owner.showLocated + " or one of its subclasses"
whyNot.append(i"""
| Protected $alt can only be accessed from $location.""")
val cls = alt.owner.enclosingSubClass
val owner = if cls.exists then cls else alt.owner
val location =
if alt.is(Protected) && !owner.is(Final) then owner.showLocated + " or one of its subclasses"
else if alt.privateWithin.exists then alt.privateWithin.showLocated
else owner.showLocated
val accessMod =
if alt.is(Protected) then "protected"
else if alt.is(Private) then "private"
else i"private[${alt.privateWithin.name}]"
whyNot.append(i"""
| $accessMod $alt can only be accessed from $location.""")
i"$whatCanNot be accessed as a member of $pre$where.$whyNot"
def explain(using Context) = ""

Expand Down
2 changes: 1 addition & 1 deletion tests/neg/i12573.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
|Extension methods were tried, but the search failed with:
|
| method getDFType cannot be accessed as a member of DFType.type from the top-level definitions in package <empty>.
| Protected method getDFType can only be accessed from object DFType.
| protected method getDFType can only be accessed from object DFType.
1 change: 1 addition & 0 deletions tests/neg/i14432c.check
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
12 |class Bar extends example.Foo(23) { // error: cant access private[example] ctor
| ^^^^^^^^^^^
| constructor Foo cannot be accessed as a member of example.Foo from class Bar.
| private[example] constructor Foo can only be accessed from package example.
-- [E172] Type Error: tests/neg/i14432c.scala:16:43 --------------------------------------------------------------------
16 | val mFoo = summon[Mirror.Of[example.Foo]] // error: no mirror
| ^
Expand Down
25 changes: 16 additions & 9 deletions tests/neg/i18686.check
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
-- [E173] Reference Error: tests/neg/i18686.scala:9:16 -----------------------------------------------------------------
9 | println(Foo.Bar1) // error
| ^^^^^^^^
| value Bar1 cannot be accessed as a member of Foo.type from object Main.
-- [E173] Reference Error: tests/neg/i18686.scala:10:16 ----------------------------------------------------------------
10 | println(Foo.Bar2) // error
-- [E173] Reference Error: tests/neg/i18686.scala:11:16 ----------------------------------------------------------------
11 | println(Foo.Bar1) // error
| ^^^^^^^^
| value Bar1 cannot be accessed as a member of Foo.type from object Main.
| private value Bar1 can only be accessed from object Foo.
-- [E173] Reference Error: tests/neg/i18686.scala:12:16 ----------------------------------------------------------------
12 | println(Foo.Bar2) // error
| ^^^^^^^^
| value Bar2 cannot be accessed as a member of Foo.type from object Main.
-- [E173] Reference Error: tests/neg/i18686.scala:11:16 ----------------------------------------------------------------
11 | println(Foo.Bar3) // error
| private[Foo] value Bar2 can only be accessed from object Foo.
-- [E173] Reference Error: tests/neg/i18686.scala:13:16 ----------------------------------------------------------------
13 | println(Foo.Bar3) // error
| ^^^^^^^^
| value Bar3 cannot be accessed as a member of Foo.type from object Main.
| Protected value Bar3 can only be accessed from object Foo.
| protected value Bar3 can only be accessed from object Foo.
-- [E173] Reference Error: tests/neg/i18686.scala:14:20 ----------------------------------------------------------------
14 | println(Foo.Baz.Bar4) // error
| ^^^^^^^^^^^^
| value Bar4 cannot be accessed as a member of Foo.Baz.type from object Main.
| private[Foo] value Bar4 can only be accessed from object Foo.
7 changes: 5 additions & 2 deletions tests/neg/i18686.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
object Foo:
private val Bar1: Int = 3
private[Foo] val Bar2: Int = 3
private val Bar1: Int = 1
private[Foo] val Bar2: Int = 2
protected val Bar3: Int = 3
object Baz:
private[Foo] val Bar4: Int = 4
end Foo

object Main:
def main(args: Array[String]): Unit =
println(Foo.Bar1) // error
println(Foo.Bar2) // error
println(Foo.Bar3) // error
println(Foo.Baz.Bar4) // error
end main
end Main
16 changes: 8 additions & 8 deletions tests/neg/i7709.check
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,39 @@
5 | class B extends X.Y // error
| ^^^
| class Y cannot be accessed as a member of X.type from class B.
| Protected class Y can only be accessed from object X.
| protected class Y can only be accessed from object X.
-- [E173] Reference Error: tests/neg/i7709.scala:6:21 ------------------------------------------------------------------
6 | class B2 extends X.Y: // error
| ^^^
| class Y cannot be accessed as a member of X.type from class B2.
| Protected class Y can only be accessed from object X.
| protected class Y can only be accessed from object X.
-- [E173] Reference Error: tests/neg/i7709.scala:9:28 ------------------------------------------------------------------
9 | class B4 extends B3(new X.Y) // error
| ^^^
| class Y cannot be accessed as a member of X.type from class B4.
| Protected class Y can only be accessed from object X.
| protected class Y can only be accessed from object X.
-- [E173] Reference Error: tests/neg/i7709.scala:11:34 -----------------------------------------------------------------
11 | def this(n: Int) = this(new X.Y().toString) // error
| ^^^
| class Y cannot be accessed as a member of X.type from class B5.
| Protected class Y can only be accessed from object X.
| protected class Y can only be accessed from object X.
-- [E173] Reference Error: tests/neg/i7709.scala:13:20 -----------------------------------------------------------------
13 | class B extends X.Y // error
| ^^^
| class Y cannot be accessed as a member of X.type from class B.
| Protected class Y can only be accessed from object X.
| protected class Y can only be accessed from object X.
-- [E173] Reference Error: tests/neg/i7709.scala:18:18 -----------------------------------------------------------------
18 | def y = new xx.Y // error
| ^^^^
| class Y cannot be accessed as a member of XX from class C.
| Protected class Y can only be accessed from class XX or one of its subclasses.
| protected class Y can only be accessed from class XX or one of its subclasses.
-- [E173] Reference Error: tests/neg/i7709.scala:23:20 -----------------------------------------------------------------
23 | def y = new xx.Y // error
| ^^^^
| class Y cannot be accessed as a member of XX from class D.
| Protected class Y can only be accessed from class XX or one of its subclasses.
| protected class Y can only be accessed from class XX or one of its subclasses.
-- [E173] Reference Error: tests/neg/i7709.scala:31:20 -----------------------------------------------------------------
31 | class Q extends X.Y // error
| ^^^
| class Y cannot be accessed as a member of p.X.type from class Q.
| Protected class Y can only be accessed from object X in package p.
| protected class Y can only be accessed from object X in package p.
5 changes: 5 additions & 0 deletions tests/neg/not-accessible.check
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@
8 | def test(a: A) = a.x // error
| ^^^
| value x cannot be accessed as a member of (a : foo.A) from class B.
| private[A] value x can only be accessed from class A in package foo.
-- [E173] Reference Error: tests/neg/not-accessible.scala:10:23 --------------------------------------------------------
10 | def test(a: A) = a.x // error
| ^^^
| value x cannot be accessed as a member of (a : foo.A) from object B.
| private[A] value x can only be accessed from class A in package foo.
-- [E173] Reference Error: tests/neg/not-accessible.scala:13:23 --------------------------------------------------------
13 | def test(a: A) = a.x // error
| ^^^
| value x cannot be accessed as a member of (a : foo.A) from the top-level definitions in package bar.
| private[A] value x can only be accessed from class A in package foo.
-- [E173] Reference Error: tests/neg/not-accessible.scala:5:21 ---------------------------------------------------------
5 | def test(a: A) = a.x // error
| ^^^
| value x cannot be accessed as a member of (a : foo.A) from the top-level definitions in package foo.
| private[A] value x can only be accessed from class A in package foo.
-- [E173] Reference Error: tests/neg/not-accessible.scala:15:23 --------------------------------------------------------
15 |def test(a: foo.A) = a.x // error
| ^^^
| value x cannot be accessed as a member of (a : foo.A) from the top-level definitions in package <empty>.
| private[A] value x can only be accessed from class A in package foo.

0 comments on commit 899dc46

Please sign in to comment.