Skip to content
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

Allow override protected[C] in companion #14105

Merged
merged 2 commits into from Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 13 additions & 10 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Expand Up @@ -409,19 +409,21 @@ object RefChecks {
overrideError("has weaker access privileges; it should not be private")

// todo: align accessibility implication checking with isAccessible in Contexts
val ob = other.accessBoundary(member.owner)
val mb = member.accessBoundary(member.owner)
def isOverrideAccessOK =
(member.flags & AccessFlags).isEmpty
&& !member.privateWithin.exists // member is public, or
|| (!other.is(Protected) || member.is(Protected))
// if o is protected, so is m, and
&& (ob.isContainedIn(mb) || other.isAllOf(JavaProtected))
// m relaxes o's access boundary,
// or o is Java defined and protected (see #3946)
val memberIsPublic = (member.flags & AccessFlags).isEmpty && !member.privateWithin.exists
def protectedOK = !other.is(Protected) || member.is(Protected) // if o is protected, so is m
def accessBoundaryOK =
val ob = other.accessBoundary(member.owner)
val mb = member.accessBoundary(member.owner)
// restriction isLocalToBlock because companionModule fails under -from-tasty
TheElectronWill marked this conversation as resolved.
Show resolved Hide resolved
def companionBoundaryOK = ob.isClass && !ob.isLocalToBlock && mb.is(Module) && (ob.companionModule eq mb.companionModule)
ob.isContainedIn(mb) || companionBoundaryOK // m relaxes o's access boundary,
def otherIsJavaProtected = other.isAllOf(JavaProtected) // or o is Java defined and protected (see #3946)
memberIsPublic || protectedOK && (accessBoundaryOK || otherIsJavaProtected)
end isOverrideAccessOK
if !member.hasTargetName(other.targetName) then
overrideTargetNameError()
else if (!isOverrideAccessOK)
else if !isOverrideAccessOK then
overrideAccessError()
else if (other.isClass)
// direct overrides were already checked on completion (see Checking.chckWellFormed)
Expand Down Expand Up @@ -502,6 +504,7 @@ object RefChecks {
else
checkOverrideDeprecated()
}
end checkOverride

/* TODO enable; right now the annotation is scala-private, so cannot be seen
* here.
Expand Down
17 changes: 17 additions & 0 deletions tests/neg/t12494.scala
@@ -0,0 +1,17 @@

object X {
// restriction in Scala 2 for local companions
// restriction in Scala 3 under -from-tasty
def m: Int = {
trait C {
protected[C] def f: Int
}
object C {
class C2 extends C {
protected[C] def f: Int = 42 // error // ok except for restrictions noted
def test = f
}
}
C.C2().test
}
}
10 changes: 10 additions & 0 deletions tests/pos/t12494.scala
@@ -0,0 +1,10 @@

trait Base {
protected[Base] def f: Int
}
object Base {
class Child extends Base {
protected[Base] def f: Int = 42 // ok
def test = f
}
}