Skip to content

Commit 4fd4142

Browse files
committed
Protected case class constructor -> private apply
1 parent 847cce2 commit 4fd4142

File tree

4 files changed

+30
-29
lines changed

4 files changed

+30
-29
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -693,23 +693,11 @@ object desugar {
693693
// For all other classes, the parent is AnyRef.
694694
val companions =
695695
if (isCaseClass) {
696-
697-
// true if access to the apply method has to be restricted
698-
// i.e. if the case class constructor is either private or qualified private
699-
def restrictedAccess = {
700-
val mods = constr1.mods
701-
mods.is(Private) || (!mods.is(Protected) && mods.hasPrivateWithin)
702-
}
703-
704696
val applyMeths =
705697
if (mods.is(Abstract)) Nil
706698
else {
707-
val copiedFlagsMask = copiedAccessFlags & Private
708-
val appMods = {
709-
val mods = Modifiers(Synthetic | constr1.mods.flags & copiedFlagsMask)
710-
if (restrictedAccess) mods.withPrivateWithin(constr1.mods.privateWithin)
711-
else mods
712-
}
699+
val appMods =
700+
Modifiers(Synthetic | constr1.mods.flags & copiedAccessFlags).withPrivateWithin(constr1.mods.privateWithin)
713701
val appParamss =
714702
derivedVparamss.nestedZipWithConserve(constrVparamss)((ap, cp) =>
715703
ap.withMods(ap.mods | (cp.mods.flags & HasDefault)))

tests/neg/caseclass-access.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
case class A private (i: Int)
22
object A
33
object ATest {
4+
def a0: A = new A(0) // error: constructor is private
45
def a1: A = A(1) // error: apply is private
56
def a2: A = a1.copy(2) // error: copy is private
67
}
78

89
case class B private (i: Int) // ok: no user-defined companion object
910
object BTest {
11+
def b0: B = new B(0) // error: constructor is private
1012
def b1: B = B(1) // error: apply is private
1113
def b2: B = b1.copy(2) // error: copy is private
1214
}
@@ -19,24 +21,30 @@ object qualified_private {
1921
}
2022
object QPrivTest {
2123
import qualified_private.*
24+
def c0: C = new C(0) // error: constructor is private
2225
def c1: C = C(1) // error: apply is private
2326
def c2: C = c1.copy(2) // error: copy is private
2427

28+
def d0: D = new D(0) // error: constructor is private
2529
def d1: D = D(1) // error: apply is private
2630
def d2: D = d1.copy(2) // error: copy is private
2731
}
2832

2933
case class E protected (i: Int)
3034
object ETest {
31-
def e1: E = E(1)
32-
def e2: E = e2.copy(2) // error: copy is protected
35+
def e0: E = new E(0) // error: constructor is protected
36+
def e1: E = E(1) // error: apply is protected
37+
def e2: E = e1.copy(2) // error: copy is protected
38+
def eta: Int => E = E // error: apply is protected
3339
}
3440

3541
object qualified_protected {
3642
case class F protected[qualified_protected] (i: Int)
3743
}
3844
object QProtTest {
3945
import qualified_protected.*
40-
def f1: F = F(1)
41-
def f2: F = f2.copy(2) // error: copy is protected
46+
def f0: F = new F(0) // error: constructor is protected
47+
def f1: F = F(1) // error: apply is protected
48+
def f2: F = f1.copy(2) // error: copy is protected
49+
def eta: Int => F = F // error: apply is protected
4250
}

tests/neg/i14187.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
sealed case class Foo protected (i: Int, j: Int)
2+
3+
final class Bar(n: Int) extends Foo(n, n)
4+
5+
class Other:
6+
def foo = Foo(1, 2) // error
7+
def foo2 = Foo.apply(1, 2) // error

tests/pos/caseclass-access.scala

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,45 @@
11
case class A private (i: Int)
22
object A {
3+
def a0 = new A(0) // constructor is accessible in companion
34
def a = A(1).copy(2) // apply and copy are accessible in companion
45
}
56

67
case class B private (i: Int) { // no user-defined companion object, should compile
8+
def b0 = new B(0) // constructor is accessible
79
def b = B(1).copy(2) // apply and copy are accessible
810
}
911

1012
object qualified_private {
1113
case class A private[qualified_private] (i: Int)
1214
object A {
15+
def a0 = new A(0) // constructor is accessible in companion
1316
def a = A(1).copy(2) // apply and copy are accessible in companion
1417
}
1518

19+
def a0 = new A(0) // constructor is accessible in qualified_private object
1620
def a = A(1).copy(2) // apply and copy are accessible in qualified_private object
1721

1822
case class B private[qualified_private] (i: Int) { // no user-defined companion object, should compile
23+
def b0 = new B(0) // constructor is accessible
1924
def b = B(1).copy(2) // apply and copy are accessible
2025
}
2126

27+
def b0 = new B(0) // constructor is accessible in qualified_private object
2228
def b = B(1).copy(2) // apply and copy are accessible in qualified_private object
2329
}
2430

2531
case class C protected (i: Int)
2632
class CSub extends C(1) {
2733
def c = copy(2) // copy is accessible in subclass
2834
}
29-
object CTest {
30-
def c = C(1) // apply is public
31-
}
3235

3336
object qualified_protected {
3437
case class C protected[qualified_protected] (i: Int)
3538
class CSub extends C(1) {
3639
def c = copy(2) // copy is accessible in subclass
3740
}
38-
object CTest {
39-
def c = C(1) // apply is public
40-
def checkExtendsFunction: Int => C = C // companion extends (Int => C)
41-
}
41+
def eta: Int => C = C // can eta-expand C.apply method
4242

43-
def c = C(1).copy(2)
44-
}
45-
object CQualifiedTest {
46-
def c = qualified_protected.C(1) // apply is public
43+
def c0 = new C(0) // constructor is accessible in qualified_protected object
44+
def c = C(1).copy(2) // apply and copy are accessible in qualified_protected object
4745
}

0 commit comments

Comments
 (0)