Skip to content

Commit f42efa3

Browse files
committed
Additional tests and comments around mkZero for value classes
1 parent d98bcdc commit f42efa3

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

src/main/scala/scala/async/internal/TransformUtils.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,20 @@ private[async] trait TransformUtils {
333333
def mkZero(tp: Type): Tree = {
334334
if (tp.typeSymbol.asClass.isDerivedValueClass) {
335335
val argZero = mkZero(derivedValueClassUnbox(tp.typeSymbol).infoIn(tp).resultType)
336+
val baseType = tp.baseType(tp.typeSymbol) // use base type here to dealias / strip phantom "tagged types" etc.
337+
338+
// By explicitly attributing the types and symbols here, we subvert privacy.
339+
// Otherwise, ticket86PrivateValueClass would fail.
340+
341+
// Approximately:
342+
// q"new ${valueClass}[$..targs](argZero)"
336343
val target: Tree = gen.mkAttributedSelect(
337344
c.typecheck(atMacroPos(
338-
New(TypeTree(tp.baseType(tp.typeSymbol))))), tp.typeSymbol.asClass.primaryConstructor)
345+
New(TypeTree(baseType)))), tp.typeSymbol.asClass.primaryConstructor)
346+
339347
val zero = gen.mkMethodCall(target, argZero :: Nil)
348+
349+
// restore the original type which we might otherwise have weakened with `baseType` above
340350
gen.mkCast(zero, tp)
341351
} else {
342352
gen.mkZero(tp)

src/test/scala/scala/async/run/toughtype/ToughType.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,37 @@ class ToughTypeSpec {
286286
val result = Await.result(fut, 5.seconds)
287287
result mustBe None
288288
}
289+
290+
@Test def ticket86PrivateValueClass(): Unit = {
291+
import ExecutionContext.Implicits.global
292+
293+
def doAThing(param: PrivateWrapper) = Future(None)
294+
295+
val fut = async {
296+
Option(PrivateWrapper.Instance) match {
297+
case Some(valueHolder) =>
298+
await(doAThing(valueHolder))
299+
case None =>
300+
None
301+
}
302+
}
303+
304+
val result = Await.result(fut, 5.seconds)
305+
result mustBe None
306+
}
289307
}
290308

291309
class IntWrapper(val value: String) extends AnyVal {
292310
def plusStr = Future.successful(value + "!")
293311
}
294312
class ParamWrapper[T](val value: T) extends AnyVal
295313

314+
class PrivateWrapper private (private val value: String) extends AnyVal
315+
object PrivateWrapper {
316+
def Instance = new PrivateWrapper("")
317+
}
318+
319+
296320
trait A
297321

298322
trait B

0 commit comments

Comments
 (0)