From 1472b7a4975106b224489e854cbedcb09db7ecb7 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 13 Oct 2023 10:18:13 +0200 Subject: [PATCH] Improve error message for inaccessible protected members --- .../tools/dotc/core/SymDenotations.scala | 8 +++---- .../tools/dotc/printing/RefinedPrinter.scala | 2 +- tests/neg-macros/annot-result-owner.check | 2 +- tests/neg/i12573.check | 5 ++-- tests/neg/i7709.check | 24 +++++++------------ tests/neg/not-accessible.check | 6 ++--- 6 files changed, 19 insertions(+), 28 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 3d43a99a564c..010314187694 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -915,17 +915,17 @@ object SymDenotations { true else val encl = if ctx.owner.isConstructor then ctx.owner.enclosingClass.owner.enclosingClass else ctx.owner.enclosingClass + val location = if owner.is(Final) then owner.showLocated else owner.showLocated + " or one of its subclasses" fail(i""" - | Access to protected $this not permitted because enclosing ${encl.showLocated} - | is not a subclass of ${owner.showLocated} where target is defined""") + | Protected $this can only be accessed from $location.""") else if isType || pre.derivesFrom(cls) || isConstructor || owner.is(ModuleClass) then // allow accesses to types from arbitrary subclasses fixes #4737 // don't perform this check for static members true else + val location = if cls.is(Final) then cls.showLocated else cls.showLocated + " or one of its subclasses" fail(i""" - | Access to protected ${symbol.show} not permitted because prefix type ${pre.widen.show} - | does not conform to ${cls.showLocated} where the access takes place""") + | Protected $this can only be accessed from $location.""") end isProtectedAccessOK if pre eq NoPrefix then true diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index acf52308edc3..7465b5c60aa3 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -1123,7 +1123,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { nameString(sym) if sym.is(ModuleClass) && sym.isTopLevelDefinitionsObject then - "top-level definition in package " + nameString(sym.owner.name) + "the top-level definitions in package " + nameString(sym.owner.name) else (keywordText(kindString(sym)) ~~ { if (sym.isAnonymousClass) toTextParents(sym.info.parents) ~~ "{...}" diff --git a/tests/neg-macros/annot-result-owner.check b/tests/neg-macros/annot-result-owner.check index 7064f62d8970..e2209998579c 100644 --- a/tests/neg-macros/annot-result-owner.check +++ b/tests/neg-macros/annot-result-owner.check @@ -2,7 +2,7 @@ -- Error: tests/neg-macros/annot-result-owner/Test_2.scala:1:0 --------------------------------------------------------- 1 |@insertVal // error |^^^^^^^^^^ - |macro annotation @insertVal added value definitionWithWrongOwner$macro$1 with an inconsistent owner. Expected it to be owned by top-level definition in package but was owned by method foo. + |macro annotation @insertVal added value definitionWithWrongOwner$macro$1 with an inconsistent owner. Expected it to be owned by the top-level definitions in package but was owned by method foo. -- Error: tests/neg-macros/annot-result-owner/Test_2.scala:5:2 --------------------------------------------------------- 5 | @insertVal // error | ^^^^^^^^^^ diff --git a/tests/neg/i12573.check b/tests/neg/i12573.check index fa402273cada..8c744fda685b 100644 --- a/tests/neg/i12573.check +++ b/tests/neg/i12573.check @@ -4,6 +4,5 @@ |value getDFType is not a member of DFBits[(8 : Int)]. |Extension methods were tried, but the search failed with: | - | method getDFType cannot be accessed as a member of DFType.type from top-level definition in package . - | Access to protected method getDFType not permitted because enclosing top-level definition in package - | is not a subclass of object DFType where target is defined + | method getDFType cannot be accessed as a member of DFType.type from the top-level definitions in package . + | Protected method getDFType can only be accessed from object DFType. diff --git a/tests/neg/i7709.check b/tests/neg/i7709.check index 180cf1939d16..b3b4e21b9db9 100644 --- a/tests/neg/i7709.check +++ b/tests/neg/i7709.check @@ -2,47 +2,39 @@ 5 | class B extends X.Y // error | ^^^ | class Y cannot be accessed as a member of X.type from class B. - | Access to protected class Y not permitted because enclosing object A - | is not a subclass of object X where target is defined + | 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. - | Access to protected class Y not permitted because enclosing object A - | is not a subclass of object X where target is defined + | 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. - | Access to protected class Y not permitted because enclosing object A - | is not a subclass of object X where target is defined + | 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. - | Access to protected class Y not permitted because enclosing object A - | is not a subclass of object X where target is defined + | 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. - | Access to protected class Y not permitted because enclosing trait T - | is not a subclass of object X where target is defined + | 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. - | Access to protected class Y not permitted because enclosing class C - | is not a subclass of class XX where target is defined + | 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. - | Access to protected class Y not permitted because enclosing class D - | is not a subclass of class XX where target is defined + | 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. - | Access to protected class Y not permitted because enclosing package p - | is not a subclass of object X in package p where target is defined + | Protected class Y can only be accessed from object X in package p. diff --git a/tests/neg/not-accessible.check b/tests/neg/not-accessible.check index 849c255aa68e..00206d281016 100644 --- a/tests/neg/not-accessible.check +++ b/tests/neg/not-accessible.check @@ -9,12 +9,12 @@ -- [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 top-level definition in package bar. + | value x cannot be accessed as a member of (a : foo.A) from the top-level definitions in package bar. -- [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 top-level definition in package foo. + | value x cannot be accessed as a member of (a : foo.A) from the top-level definitions 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 top-level definition in package . + | value x cannot be accessed as a member of (a : foo.A) from the top-level definitions in package .