diff options
author | Paul Phillips <paulp@improving.org> | 2009-07-15 15:23:24 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-07-15 15:23:24 +0000 |
commit | b9be89ebdaba528a7590c2be2463c58ce1652dab (patch) | |
tree | ef3b4e73e50d968ce92c82ec69d1a56e23b728f1 | |
parent | 8dee86d734a85ccbc809c098e5fd7b3ea9358e74 (diff) | |
download | scala-b9be89ebdaba528a7590c2be2463c58ce1652dab.tar.gz scala-b9be89ebdaba528a7590c2be2463c58ce1652dab.tar.bz2 scala-b9be89ebdaba528a7590c2be2463c58ce1652dab.zip |
Fix and test case for #1141.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/CleanUp.scala | 71 | ||||
-rw-r--r-- | test/files/run/bug1141.check | 2 | ||||
-rw-r--r-- | test/files/run/bug1141.scala | 7 |
3 files changed, 47 insertions, 33 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 7819ced3c2..942871ae1f 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -345,6 +345,14 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } } + def boxArray(t: Tree) = { + val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe + BLOCK( + VAL(sym) === t, + IF (NULL ANY_== REF(sym)) THEN NULL ELSE gen.mkRuntimeCall(nme.boxArray, List(REF(sym))) + ) + } + /* ### BOXING PARAMS & UNBOXING RESULTS ### */ /* Transforms the result of a reflective call (always an AnyRef) to @@ -358,52 +366,49 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * is enough even for value (int et al.) values as the result of * a dynamic call will box them as a side-effect. */ def fixResult(resType: Type)(tree: Tree): Tree = localTyper typed { - def boxArray = { - val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe - BLOCK( - VAL(sym) === tree, - IF (NULL ANY_== REF(sym)) THEN NULL ELSE gen.mkRuntimeCall(nme.boxArray, List(REF(sym))) - ) - } resType.typeSymbol match { case UnitClass => BLOCK(tree, REF(BoxedUnit_UNIT)) - case ArrayClass => boxArray + case ArrayClass => boxArray(tree) case ObjectClass => tree case _ => tree AS_ATTR resType } } /* Transforms the parameters of a dynamic apply (always AnyRefs) to - * something compatible with reclective calls. The transformation depends + * something compatible with reflective calls. The transformation depends * on the method's static parameter types. * - for (unboxed) arrays, the (non-null) value is tested for its erased * type. If it is a boxed array, the array is unboxed. If it is an - * unboxed array, it is left alone. */ - def fixParams(params: List[Tree], paramTypes: List[Type]): List[Tree] = - for ((param, paramType) <- params zip paramTypes) yield { - localTyper typed { - if (paramType.typeSymbol == ArrayClass) { - val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe - assert(paramType.typeArgs.length == 1) - val arrayType = paramType.typeArgs(0).normalize - lazy val unboxMethod = getMember(BoxedArrayClass, nme.unbox) - - BLOCK( - VAL(sym) === param, - IF (NULL ANY_== REF(sym)) . - THEN (NULL) . - ELSE ( - IF (REF(sym) IS_OBJ BoxedArrayClass.tpe) . - THEN (((REF(sym) AS_ATTR BoxedArrayClass.tpe) DOT unboxMethod)(LIT(arrayType))) - ELSE - REF(sym) - ) - ) - } - else - param + * unboxed array, it is left alone - except that for varargs in structural + * types to work properly, if the parameter is an Array and the parameter + * type a Seq, it is routed through the boxed logic. */ + def fixParams(params: List[Tree], paramTypes: List[Type]): List[Tree] = { + def doUnboxedArray(param: Tree, paramType: Type) = { + val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe + assert(paramType.typeArgs.length == 1) + val arrayType = paramType.typeArgs(0).normalize + lazy val unboxMethod = getMember(BoxedArrayClass, nme.unbox) + + BLOCK( + VAL(sym) === param, + IF (NULL ANY_== REF(sym)) . + THEN (NULL) . + ELSE ( + IF (REF(sym) IS_OBJ BoxedArrayClass.tpe) . + THEN (((REF(sym) AS_ATTR BoxedArrayClass.tpe) DOT unboxMethod)(LIT(arrayType))) + ELSE + REF(sym) + ) + ) + } + for ((param, paramType) <- params zip paramTypes) yield localTyper typed { + (param.tpe, paramType.typeSymbol) match { + case (_, ArrayClass) => doUnboxedArray(param, paramType) + case (TypeRef(_, ArrayClass, _), SeqClass) => boxArray(param) // ticket #1141 + case _ => param } } + } /* ### CALLING THE APPLY -> one for operators (see above), one for normal methods ### */ def callAsOperator(paramTypes: List[Type], resType: Type): Tree = localTyper typed { diff --git a/test/files/run/bug1141.check b/test/files/run/bug1141.check new file mode 100644 index 0000000000..7262160d1d --- /dev/null +++ b/test/files/run/bug1141.check @@ -0,0 +1,2 @@ +var +args diff --git a/test/files/run/bug1141.scala b/test/files/run/bug1141.scala new file mode 100644 index 0000000000..6c8e1c7399 --- /dev/null +++ b/test/files/run/bug1141.scala @@ -0,0 +1,7 @@ +object Test extends Application { + val foo = new { + def apply(args : String*) = args foreach println + } + + foo("var", "args") +}
\ No newline at end of file |