-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SI-7859 Value classes may wrap a non-public member
We allow value class constructors to be non-public, so to be regular, we should also allow the same for the param accessor. This commit uses the 'makeNotPrivate' machinery to ensure that the backend can generate the requisite unboxing calls. This commit: - refactors the code that enforced the restrictions, improving a few error messages and positions. The remaining restrictions needed some rewording in light of this change. - allows value classes to have non-public, val parameters. private[this] / protected[this] are still disallowed as value classes don't have a concept of `this`, and because trying to accomdate then would complicate the implementation. This means that `class C(x: Int) extends AnyVal` is not allowed, the user still must write `private val x: Int` or `val x: Int`. - Outlaw `class C()()(val x: Int) extends AnyVal` to curtail any bugs that might lurk in such a formulation. The tests: - Show that the privacy is respected in the typer phase, under joint and separate compilation. We don't want a repeat performance of SI-6601. - Show that code that needs compiler-generated unboxes works under both compilation scenarios - Checks that the remaining restrictions are enforced and well communicated.
- Loading branch information
Showing
10 changed files
with
147 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
B_2.scala:6: error: not found: value x | ||
new p1.A(x).x | ||
^ | ||
B_2.scala:6: error: value x in class A cannot be accessed in p1.A | ||
new p1.A(x).x | ||
^ | ||
B_2.scala:7: error: not found: value x | ||
new B(x).x | ||
^ | ||
B_2.scala:7: error: value x is not a member of B | ||
new B(x).x | ||
^ | ||
B_2.scala:8: error: not found: value x | ||
new C(x).x | ||
^ | ||
B_2.scala:8: error: value x in class C cannot be accessed in C | ||
new C(x).x | ||
^ | ||
6 errors found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package p1 { | ||
class A(private[p1] val x: Any) extends AnyVal | ||
} | ||
class B(private val x: Any) extends AnyVal | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class C(private val x: Any) extends AnyVal | ||
|
||
// Checking that makeNotPrivate(paramAccessor) doesn't make this visible during typer. | ||
// The output is identical with/without `extends AnyVal`. | ||
object Test { | ||
new p1.A(x).x | ||
new B(x).x | ||
new C(x).x | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
class A(private val x: Int) extends AnyVal | ||
|
||
object A { | ||
val Const = new A(0) | ||
} | ||
|
||
class A1(protected val x: Int) extends AnyVal | ||
|
||
package p { | ||
class A2(private[p] val x: Int) extends AnyVal | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
class B private (private val b: Int) extends AnyVal | ||
object B { | ||
val Const = new B(0) | ||
} | ||
|
||
// These tests will require erasure to unbox the value class. | ||
// We need to test under joint and separate compilation to check | ||
// that the 'notPRIVATE' flag on the param accessor is pickled. | ||
// | ||
// See also SI-6601. | ||
object Test { | ||
def main(args: Array[String]) { | ||
unboxA | ||
unboxA1 | ||
unboxA2 | ||
unboxB | ||
} | ||
|
||
def unboxA { | ||
val o: Some[A] = Some(A.Const) | ||
val a = o.get | ||
def id(a: A): A = a | ||
id(a) | ||
} | ||
|
||
def unboxA1 { | ||
val o: Some[A1] = Some(new A1(0)) | ||
val a = o.get | ||
def id(a: A1): A1 = a | ||
id(a) | ||
} | ||
|
||
def unboxA2 { | ||
import p.A2 | ||
val o: Some[A2] = Some(new A2(0)) | ||
val a = o.get | ||
def id(a: A2): A2 = a | ||
id(a) | ||
} | ||
|
||
def unboxB { | ||
val o: Some[B] = Some(B.Const) | ||
val b = o.get | ||
def id(b: B): B = b | ||
id(b) | ||
} | ||
} |