aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-10-14 09:12:58 +0200
committerMartin Odersky <odersky@gmail.com>2016-10-14 09:16:37 +0200
commite82cb7cdb93306b5fccf6aeef0e087999f46a016 (patch)
treeea06fc1746220b1ae6864174dde02c7cd171b5fe
parentdac5b931bcf8757070c8aa74571e52f3b4c6e5eb (diff)
downloaddotty-e82cb7cdb93306b5fccf6aeef0e087999f46a016.tar.gz
dotty-e82cb7cdb93306b5fccf6aeef0e087999f46a016.tar.bz2
dotty-e82cb7cdb93306b5fccf6aeef0e087999f46a016.zip
Fix #1567: Widen private constructor in value class
Private or protected constructors of value classes need to be widenened to public in order to enable boxing anywhere. Technically we should also do something about qualified private constructors, but since we want to get rid of them anyway it's urgent.
-rw-r--r--src/dotty/tools/dotc/transform/ExtensionMethods.scala20
-rw-r--r--tests/pos/1567/PosZInt_1.scala6
-rw-r--r--tests/pos/1567/Test_2.scala3
3 files changed, 24 insertions, 5 deletions
diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
index 62a21198d..5ae4e8a54 100644
--- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala
+++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
@@ -32,6 +32,9 @@ import SymUtils._
* in [[ElimErasedValueType]].
* This is different from the implementation of value classes in Scala 2
* (see SIP-15) which uses `asInstanceOf` which does not typecheck.
+ *
+ * Finally, if the constructor of a value class is private pr protected
+ * it is widened to public.
*/
class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer =>
@@ -96,11 +99,18 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
case _ =>
moduleClassSym
}
- case ref: SymDenotation
- if isMethodWithExtension(ref) && ref.hasAnnotation(defn.TailrecAnnot) =>
- val ref1 = ref.copySymDenotation()
- ref1.removeAnnotation(defn.TailrecAnnot)
- ref1
+ case ref: SymDenotation =>
+ if (isMethodWithExtension(ref) && ref.hasAnnotation(defn.TailrecAnnot)) {
+ val ref1 = ref.copySymDenotation()
+ ref1.removeAnnotation(defn.TailrecAnnot)
+ ref1
+ }
+ else if (ref.isConstructor && isDerivedValueClass(ref.owner) && ref.is(AccessFlags)) {
+ val ref1 = ref.copySymDenotation()
+ ref1.resetFlag(AccessFlags)
+ ref1
+ }
+ else ref
case _ =>
ref
}
diff --git a/tests/pos/1567/PosZInt_1.scala b/tests/pos/1567/PosZInt_1.scala
new file mode 100644
index 000000000..60b4061e6
--- /dev/null
+++ b/tests/pos/1567/PosZInt_1.scala
@@ -0,0 +1,6 @@
+final class PosZInt private (val value: Int) extends AnyVal
+
+object PosZInt {
+ def from(value: Int): Option[PosZInt] =
+ if (value >= 0) Some(new PosZInt(value)) else None
+}
diff --git a/tests/pos/1567/Test_2.scala b/tests/pos/1567/Test_2.scala
new file mode 100644
index 000000000..db6ca7070
--- /dev/null
+++ b/tests/pos/1567/Test_2.scala
@@ -0,0 +1,3 @@
+object Test {
+ scala.util.Try(PosZInt.from(1).get)
+}