Skip to content

Commit 0cb09c2

Browse files
committed
Merge pull request #30 from retronym/topic/unchecked-bounds
Use @uncheckedBounds to avoid introducing refchecks errors …
2 parents 94d7413 + 98e2f26 commit 0cb09c2

29 files changed

+115
-83
lines changed

build.sbt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
scalaVersion := "2.10.2"
1+
scalaVersion := "2.10.3-RC1"
22

33
organization := "org.typesafe.async" // TODO new org name under scala-lang.
44

5+
// Uncomment to test with a locally built copy of Scala.
6+
// scalaHome := Some(file("/code/scala2/build/pack"))
7+
58
name := "scala-async"
69

710
version := "1.0.0-SNAPSHOT"
@@ -15,18 +18,30 @@ libraryDependencies <++= (scalaVersion) {
1518

1619
libraryDependencies += "junit" % "junit-dep" % "4.10" % "test"
1720

18-
libraryDependencies += "com.novocode" % "junit-interface" % "0.10-M2" % "test"
21+
libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test"
1922

2023
testOptions += Tests.Argument(TestFrameworks.JUnit, "-q", "-v", "-s")
2124

2225
parallelExecution in Global := false
2326

2427
autoCompilerPlugins := true
2528

26-
libraryDependencies <<= (scalaVersion, libraryDependencies) {
27-
(ver, deps) =>
28-
deps :+ compilerPlugin("org.scala-lang.plugins" % "continuations" % ver)
29-
}
29+
scalacOptions ++= (scalaHome.value match {
30+
case Some(sh) =>
31+
// Use continuations plugin from the local scala instance
32+
val continuationsJar = sh / "misc" / "scala-devel" / "plugins" / "continuations.jar"
33+
("-Xplugin:" + continuationsJar.getAbsolutePath) :: Nil
34+
case None =>
35+
Nil
36+
})
37+
38+
libraryDependencies ++= (scalaHome.value match {
39+
case Some(sh) =>
40+
Nil
41+
case None =>
42+
// Use continuations plugin from the published artifact.
43+
compilerPlugin("org.scala-lang.plugins" % "continuations" % scalaVersion.value) :: Nil
44+
})
3045

3146
scalacOptions += "-P:continuations:enable"
3247

project/build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
sbt.version=0.12.4
1+
sbt.version=0.13.0-RC5

src/main/scala/scala/async/internal/AnfTransform.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ private[async] trait AnfTransform {
119119
}
120120

121121
private def defineVar(prefix: String, tp: Type, pos: Position): ValDef = {
122-
val sym = currOwner.newTermSymbol(name.fresh(prefix), pos, MUTABLE | SYNTHETIC).setInfo(tp)
123-
ValDef(sym, gen.mkZero(tp)).setType(NoType).setPos(pos)
122+
val sym = currOwner.newTermSymbol(name.fresh(prefix), pos, MUTABLE | SYNTHETIC).setInfo(uncheckedBounds(tp))
123+
ValDef(sym, gen.mkZero(uncheckedBounds(tp))).setType(NoType).setPos(pos)
124124
}
125125
}
126126

@@ -145,7 +145,7 @@ private[async] trait AnfTransform {
145145
}
146146

147147
private def defineVal(prefix: String, lhs: Tree, pos: Position): ValDef = {
148-
val sym = currOwner.newTermSymbol(name.fresh(prefix), pos, SYNTHETIC).setInfo(lhs.tpe)
148+
val sym = currOwner.newTermSymbol(name.fresh(prefix), pos, SYNTHETIC).setInfo(uncheckedBounds(lhs.tpe))
149149
changeOwner(lhs, currentOwner, sym)
150150
ValDef(sym, changeOwner(lhs, currentOwner, sym)).setType(NoType).setPos(pos)
151151
}

src/main/scala/scala/async/internal/AsyncId.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ object IdentityFutureSystem extends FutureSystem {
4141
def execContextType: Type = weakTypeOf[Unit]
4242

4343
def createProm[A: WeakTypeTag]: Expr[Prom[A]] = reify {
44-
new Prom()
44+
new Prom[A]()
4545
}
4646

4747
def promiseToFuture[A: WeakTypeTag](prom: Expr[Prom[A]]) = reify {

src/main/scala/scala/async/internal/AsyncTransform.scala

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ trait AsyncTransform {
66
import global._
77

88
def asyncTransform[T](body: Tree, execContext: Tree, cpsFallbackEnabled: Boolean)
9-
(implicit resultType: WeakTypeTag[T]): Tree = {
9+
(resultType: WeakTypeTag[T]): Tree = {
10+
11+
// We annotate the type of the whole expression as `T @uncheckedBounds` so as not to introduce
12+
// warnings about non-conformant LUBs. See SI-7694
13+
// This implicit propatages the annotated type in the type tag.
14+
implicit val uncheckedBoundsResultTag: WeakTypeTag[T] = WeakTypeTag[T](rootMirror, FixedMirrorTypeCreator(rootMirror, uncheckedBounds(resultType.tpe)))
1015

1116
reportUnsupportedAwaits(body, report = !cpsFallbackEnabled)
1217

@@ -22,12 +27,12 @@ trait AsyncTransform {
2227
DefDef(NoMods, name.apply, Nil, applyVParamss, TypeTree(definitions.UnitTpe), Literal(Constant(())))
2328
}
2429

25-
val stateMachineType = applied("scala.async.StateMachine", List(futureSystemOps.promType[T], futureSystemOps.execContextType))
30+
val stateMachineType = applied("scala.async.StateMachine", List(futureSystemOps.promType[T](uncheckedBoundsResultTag), futureSystemOps.execContextType))
2631

2732
val stateMachine: ClassDef = {
2833
val body: List[Tree] = {
2934
val stateVar = ValDef(Modifiers(Flag.MUTABLE | Flag.PRIVATE | Flag.LOCAL), name.state, TypeTree(definitions.IntTpe), Literal(Constant(0)))
30-
val result = ValDef(NoMods, name.result, TypeTree(futureSystemOps.promType[T]), futureSystemOps.createProm[T].tree)
35+
val result = ValDef(NoMods, name.result, TypeTree(futureSystemOps.promType[T](uncheckedBoundsResultTag)), futureSystemOps.createProm[T](uncheckedBoundsResultTag).tree)
3136
val execContextValDef = ValDef(NoMods, name.execContext, TypeTree(), execContext)
3237

3338
val apply0DefDef: DefDef = {

src/main/scala/scala/async/internal/ExprBuilder.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ trait ExprBuilder {
283283

284284
def onCompleteHandler[T: WeakTypeTag]: Tree
285285

286-
def resumeFunTree[T]: DefDef
286+
def resumeFunTree[T: WeakTypeTag]: DefDef
287287
}
288288

289289
case class SymLookup(stateMachineClass: Symbol, applyTrParam: Symbol) {
@@ -303,12 +303,12 @@ trait ExprBuilder {
303303
new AsyncBlock {
304304
def asyncStates = blockBuilder.asyncStates.toList
305305

306-
def mkCombinedHandlerCases[T]: List[CaseDef] = {
306+
def mkCombinedHandlerCases[T: WeakTypeTag]: List[CaseDef] = {
307307
val caseForLastState: CaseDef = {
308308
val lastState = asyncStates.last
309309
val lastStateBody = Expr[T](lastState.body)
310310
val rhs = futureSystemOps.completeProm(
311-
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), reify(scala.util.Success(lastStateBody.splice)))
311+
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), reify(scala.util.Success[T](lastStateBody.splice)))
312312
mkHandlerCase(lastState.state, rhs.tree)
313313
}
314314
asyncStates.toList match {
@@ -337,7 +337,7 @@ trait ExprBuilder {
337337
* }
338338
* }
339339
*/
340-
def resumeFunTree[T]: DefDef =
340+
def resumeFunTree[T: WeakTypeTag]: DefDef =
341341
DefDef(Modifiers(), name.resume, Nil, List(Nil), Ident(definitions.UnitClass),
342342
Try(
343343
Match(symLookup.memberRef(name.state), mkCombinedHandlerCases[T]),

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,19 @@ private[async] trait TransformUtils {
244244
// Attributed version of `TreeGen#mkCastPreservingAnnotations`
245245
def mkAttributedCastPreservingAnnotations(tree: Tree, tp: Type): Tree = {
246246
atPos(tree.pos) {
247-
val casted = gen.mkAttributedCast(tree, tp.withoutAnnotations.dealias)
247+
val casted = gen.mkAttributedCast(tree, uncheckedBounds(tp.withoutAnnotations).dealias)
248248
Typed(casted, TypeTree(tp)).setType(tp)
249249
}
250250
}
251+
252+
// =====================================
253+
// Copy/Pasted from Scala 2.10.3. See SI-7694.
254+
private lazy val UncheckedBoundsClass = {
255+
global.rootMirror.getClassIfDefined("scala.reflect.internal.annotations.uncheckedBounds")
256+
}
257+
final def uncheckedBounds(tp: Type): Type = {
258+
if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp
259+
else tp.withAnnotation(AnnotationInfo marker UncheckedBoundsClass.tpe)
260+
}
261+
// =====================================
251262
}

src/test/scala/scala/async/TreeInterrogation.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44

55
package scala.async
66

7-
import org.junit.runner.RunWith
8-
import org.junit.runners.JUnit4
97
import org.junit.Test
108
import scala.async.internal.AsyncId
119
import AsyncId._
1210
import tools.reflect.ToolBox
1311

14-
@RunWith(classOf[JUnit4])
1512
class TreeInterrogation {
1613
@Test
1714
def `a minimal set of vals are lifted to vars`() {

src/test/scala/scala/async/neg/LocalClasses0Spec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55
package scala.async
66
package neg
77

8-
import org.junit.runner.RunWith
9-
import org.junit.runners.JUnit4
108
import org.junit.Test
119
import scala.async.internal.AsyncId
1210

13-
@RunWith(classOf[JUnit4])
1411
class LocalClasses0Spec {
1512
@Test
1613
def localClassCrashIssue16() {

src/test/scala/scala/async/neg/NakedAwait.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@
55
package scala.async
66
package neg
77

8-
import org.junit.runner.RunWith
9-
import org.junit.runners.JUnit4
108
import org.junit.Test
119

12-
@RunWith(classOf[JUnit4])
1310
class NakedAwait {
1411
@Test
1512
def `await only allowed in async neg`() {

src/test/scala/scala/async/neg/SampleNegSpec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@
55
package scala.async
66
package neg
77

8-
import org.junit.runner.RunWith
9-
import org.junit.runners.JUnit4
108
import org.junit.Test
119

12-
@RunWith(classOf[JUnit4])
1310
class SampleNegSpec {
1411
@Test
1512
def `missing symbol`() {

src/test/scala/scala/async/run/anf/AnfTransformSpec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import scala.concurrent.{Future, ExecutionContext, future, Await}
1111
import scala.concurrent.duration._
1212
import scala.async.Async.{async, await}
1313
import org.junit.Test
14-
import org.junit.runner.RunWith
15-
import org.junit.runners.JUnit4
1614
import scala.async.internal.AsyncId
1715

1816

@@ -70,7 +68,6 @@ object State {
7068
@volatile var result: Int = 0
7169
}
7270

73-
@RunWith(classOf[JUnit4])
7471
class AnfTransformSpec {
7572

7673
@Test

src/test/scala/scala/async/run/await0/Await0Spec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ import language.{reflectiveCalls, postfixOps}
1515
import scala.concurrent.{Future, ExecutionContext, future, Await}
1616
import scala.concurrent.duration._
1717
import scala.async.Async.{async, await}
18-
import org.junit.runner.RunWith
19-
import org.junit.runners.JUnit4
2018
import org.junit.Test
2119

2220
class Await0Class {
@@ -63,7 +61,6 @@ class Await0Class {
6361
}
6462
}
6563

66-
@RunWith(classOf[JUnit4])
6764
class Await0Spec {
6865

6966
@Test

src/test/scala/scala/async/run/block0/AsyncSpec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import scala.concurrent.{Future, ExecutionContext, future, Await}
1111
import scala.concurrent.duration._
1212
import scala.async.Async.{async, await}
1313
import org.junit.Test
14-
import org.junit.runner.RunWith
15-
import org.junit.runners.JUnit4
1614

1715

1816
class Test1Class {
@@ -39,7 +37,6 @@ class Test1Class {
3937
}
4038

4139

42-
@RunWith(classOf[JUnit4])
4340
class AsyncSpec {
4441

4542
@Test

src/test/scala/scala/async/run/block1/block1.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import scala.concurrent.{Future, ExecutionContext, future, Await}
1111
import scala.concurrent.duration._
1212
import scala.async.Async.{async, await}
1313
import org.junit.Test
14-
import org.junit.runner.RunWith
15-
import org.junit.runners.JUnit4
1614

1715

1816
class Test1Class {
@@ -32,7 +30,6 @@ class Test1Class {
3230
}
3331
}
3432

35-
@RunWith(classOf[JUnit4])
3633
class Block1Spec {
3734

3835
@Test def `support a simple await`() {

src/test/scala/scala/async/run/cps/CPSSpec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ import scala.concurrent.duration._
1111
import scala.async.continuations.CPSBasedAsync._
1212
import scala.util.continuations._
1313

14-
import org.junit.runner.RunWith
15-
import org.junit.runners.JUnit4
1614
import org.junit.Test
1715

18-
@RunWith(classOf[JUnit4])
1916
class CPSSpec {
2017

2118
import ExecutionContext.Implicits.global

src/test/scala/scala/async/run/exceptions/ExceptionsSpec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ import scala.concurrent.duration._
1414
import scala.reflect.ClassTag
1515

1616
import org.junit.Test
17-
import org.junit.runner.RunWith
18-
import org.junit.runners.JUnit4
1917

20-
@RunWith(classOf[JUnit4])
2118
class ExceptionsSpec {
2219

2320
@Test

src/test/scala/scala/async/run/futures/FutureSpec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ import scala.util.{Try,Success,Failure}
1818
import scala.async.Async.{async, await}
1919

2020
import org.junit.Test
21-
import org.junit.runner.RunWith
22-
import org.junit.runners.JUnit4
2321

24-
@RunWith(classOf[JUnit4])
2522
class FutureSpec {
2623

2724
/* some utils */

src/test/scala/scala/async/run/hygiene/Hygiene.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@ package run
77
package hygiene
88

99
import org.junit.Test
10-
import org.junit.runner.RunWith
11-
import org.junit.runners.JUnit4
1210
import scala.async.internal.AsyncId
1311

14-
@RunWith(classOf[JUnit4])
1512
class HygieneSpec {
1613

1714
import AsyncId.{async, await}

src/test/scala/scala/async/run/ifelse0/IfElse0.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import language.{reflectiveCalls, postfixOps}
1010
import scala.concurrent.{Future, ExecutionContext, future, Await}
1111
import scala.concurrent.duration._
1212
import scala.async.Async.{async, await}
13-
import org.junit.runner.RunWith
14-
import org.junit.runners.JUnit4
1513
import org.junit.Test
1614
import scala.async.internal.AsyncId
1715

@@ -39,7 +37,6 @@ class TestIfElseClass {
3937
}
4038

4139

42-
@RunWith(classOf[JUnit4])
4340
class IfElseSpec {
4441

4542
@Test def `support await in a simple if-else expression`() {

src/test/scala/scala/async/run/ifelse0/WhileSpec.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@ package scala.async
66
package run
77
package ifelse0
88

9-
import org.junit.runner.RunWith
10-
import org.junit.runners.JUnit4
119
import org.junit.Test
1210
import scala.async.internal.AsyncId
1311

14-
@RunWith(classOf[JUnit4])
1512
class WhileSpec {
1613

1714
@Test

src/test/scala/scala/async/run/ifelse1/IfElse1.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import language.{reflectiveCalls, postfixOps}
1010
import scala.concurrent.{Future, ExecutionContext, future, Await}
1111
import scala.concurrent.duration._
1212
import scala.async.Async.{async, await}
13-
import org.junit.runner.RunWith
14-
import org.junit.runners.JUnit4
1513
import org.junit.Test
1614

1715

@@ -91,7 +89,6 @@ class TestIfElse1Class {
9189
}
9290
}
9391

94-
@RunWith(classOf[JUnit4])
9592
class IfElse1Spec {
9693

9794
@Test

src/test/scala/scala/async/run/ifelse2/ifelse2.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import language.{reflectiveCalls, postfixOps}
1010
import scala.concurrent.{Future, ExecutionContext, future, Await}
1111
import scala.concurrent.duration._
1212
import scala.async.Async.{async, await}
13-
import org.junit.runner.RunWith
14-
import org.junit.runners.JUnit4
1513
import org.junit.Test
1614

1715

@@ -37,7 +35,6 @@ class TestIfElse2Class {
3735
}
3836
}
3937

40-
@RunWith(classOf[JUnit4])
4138
class IfElse2Spec {
4239

4340
@Test

0 commit comments

Comments
 (0)