Skip to content

Context for constructor error is outer context #9893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 14 additions & 19 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -824,30 +824,25 @@ object SymDenotations {
}

/** Is protected access to target symbol permitted? */
def isProtectedAccessOK = {
def fail(str: => String): Boolean = {
if (whyNot != null) whyNot append str
def isProtectedAccessOK: Boolean =
inline def fail(str: String): false =
if whyNot != null then whyNot.append(str)
false
}
val cls = owner.enclosingSubClass
if (!cls.exists)
fail(
i"""
| Access to protected $this not permitted because enclosing ${ctx.owner.enclosingClass.showLocated}
if !cls.exists then
val encl = if ctx.owner.isConstructor then ctx.owner.enclosingClass.owner.enclosingClass else ctx.owner.enclosingClass
fail(i"""
| Access to protected $this not permitted because enclosing ${encl.showLocated}
| is not a subclass of ${owner.showLocated} where target is defined""")
else if
!( isType // allow accesses to types from arbitrary subclasses fixes #4737
|| pre.derivesFrom(cls)
|| isConstructor
|| owner.is(ModuleClass) // don't perform this check for static members
)
then
fail(
i"""
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
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""")
else true
}
end isProtectedAccessOK

if pre eq NoPrefix then true
else if isAbsent() then false
Expand Down
48 changes: 48 additions & 0 deletions tests/neg/i7709.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
-- Error: tests/neg/i7709.scala:5:20 -----------------------------------------------------------------------------------
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
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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
31 changes: 31 additions & 0 deletions tests/neg/i7709.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

object X:
protected class Y
object A:
class B extends X.Y // error
class B2 extends X.Y: // error
def this(n: Int) = this()
class B3(x: Any)
class B4 extends B3(new X.Y) // error
class B5(x: String):
def this(n: Int) = this(new X.Y().toString) // error
trait T:
class B extends X.Y // error
class XX:
protected class Y
class C:
def xx = new XX
def y = new xx.Y // error
class D:
def this(n: Int) = {
this()
def xx = new XX
def y = new xx.Y // error
}
class YY extends XX:
def y = new Y

package p:
object X:
protected class Y
class Q extends X.Y // error