summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2013-01-10 13:25:33 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-01-10 14:30:35 -0800
commit51f574ac9ff0dbcb665f48a8c1a380c59f2bb641 (patch)
treed0b31dfb0252b1af55e22acb2d854daf95dcdb51
parente314ff1621ee26e1e4ec65abc6e360a7731bf488 (diff)
downloadscala-51f574ac9ff0dbcb665f48a8c1a380c59f2bb641.tar.gz
scala-51f574ac9ff0dbcb665f48a8c1a380c59f2bb641.tar.bz2
scala-51f574ac9ff0dbcb665f48a8c1a380c59f2bb641.zip
clean up synthesizePartialFunction
implement the following review comments by @retronym: - [x] Please clothe this naked assert. - [x] Use match to dissect targs and check isFullyDefined. - [x] Instead of `targs.head`/`targs.last`, use `val argTp :: resTp :: Nil = targs`. - [x] Add a quasi-quote-style comment for `apply`. - [x] Factor out mkCastPreservingAnnotations.
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala27
3 files changed, 22 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 5cb43575b8..96146b7343 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -253,6 +253,11 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
}
}
+ // drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any
+ // let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree
+ def mkCastPreservingAnnotations(tree: Tree, pt: Type) =
+ Typed(mkCast(tree, pt.withoutAnnotations.dealias), TypeTree(pt))
+
/** Generate a cast for tree Tree representing Array with
* elem type elemtp to expected type pt.
*/
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index fa8aff5cdd..d73fb680f2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -1478,14 +1478,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder) // NOTE: checker must be the target of the ==, that's the patmat semantics for ya
def and(a: Tree, b: Tree): Tree = a AND b
- // drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any
- // let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree
- private def mkCast(t: Tree, tp: Type) =
- Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp)
-
// the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly)
- def _asInstanceOf(t: Tree, tp: Type): Tree = if (t.tpe != NoType && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp)
- def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp)
+ def _asInstanceOf(t: Tree, tp: Type): Tree = if (t.tpe != NoType && t.isTyped && typesConform(t.tpe, tp)) t else gen.mkCastPreservingAnnotations(t, tp)
+ def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else gen.mkCastPreservingAnnotations(REF(b), tp)
def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false)
// if (typesConform(b.info, tpX)) { patmatDebug("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE }
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 441ea6898b..be00aebf1b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2612,21 +2612,21 @@ trait Typers extends Modes with Adaptations with Tags {
* however, note that pattern matching codegen is designed to run *before* uncurry
*/
def synthesizePartialFunction(paramName: TermName, paramPos: Position, tree: Tree, mode: Int, pt0: Type): Tree = {
- assert(pt0.typeSymbol == PartialFunctionClass)
+ assert(pt0.typeSymbol == PartialFunctionClass, s"PartialFunction synthesis for match in $tree requires PartialFunction expected type, but got $pt0.")
val pt = deskolemizeGADTSkolems(pt0)
val targs = pt.normalize.typeArgs
- // if targs.head isn't fully defined, we can't translate --> error
- if (targs.isEmpty || !isFullyDefined(targs.head)) {
- MissingParameterTypeAnonMatchError(tree, pt)
- return setError(tree)
+ // if targs.head isn't fully defined, we can translate --> error
+ targs match {
+ case argTp :: _ if isFullyDefined(argTp) => // ok
+ case _ => // uh-oh
+ MissingParameterTypeAnonMatchError(tree, pt)
+ return setError(tree)
}
- val argTp = targs.head
-
- // NOTE: targs.last still might not be fully defined
- val resTp = targs.last
+ // NOTE: resTp still might not be fully defined
+ val argTp :: resTp :: Nil = targs
// targs must conform to Any for us to synthesize an applyOrElse (fallback to apply otherwise -- typically for @cps annotated targs)
val targsValidParams = targs forall (_ <:< AnyClass.tpe)
@@ -2650,10 +2650,12 @@ trait Typers extends Modes with Adaptations with Tags {
// we don't want/need the match to see the `A1` type that we must use for variance reasons in the method signature
//
// this failed: replace `selector` by `Typed(selector, TypeTree(argTp))` -- as it's an upcast, this should never fail,
- // `(x: A1): A` doesn't always type check, even though `A1 <: A`, due to singleton types
+ // `(x: A1): A` doesn't always type check, even though `A1 <: A`, due to singleton types (test/files/pos/t4269.scala)
// hence the cast, which will be erased in posterasure
- Typed(gen.mkAsInstanceOf(Ident(paramName), argTp.withoutAnnotations, true, false), TypeTree(argTp)))
- )
+ // (the cast originally caused extremely weird types to show up
+ // in test/scaladoc/run/SI-5933.scala because `variantToSkolem` was missing `tpSym.initialize`)
+ gen.mkCastPreservingAnnotations(Ident(paramName), argTp)
+ ))
def mkParam(methodSym: Symbol, tp: Type = argTp) =
methodSym.newValueParameter(paramName, paramPos.focus, SYNTHETIC) setInfo tp
@@ -2706,6 +2708,7 @@ trait Typers extends Modes with Adaptations with Tags {
}
// only used for @cps annotated partial functions
+ // `def apply(x: $argTp): $matchResTp = $selector match { $cases }`
def applyMethod = {
val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL | OVERRIDE)
val paramSym = mkParam(methodSym)