diff options
author | Martin Odersky <odersky@gmail.com> | 2009-09-17 11:00:31 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-09-17 11:00:31 +0000 |
commit | 27f573afb47fcc38627df20058fae1cfa0fcb947 (patch) | |
tree | 20b3a7d1a1e7a4a4542d4c307bf90a4a2f02ec6b /src/compiler | |
parent | 63089db7fb68d070a2fdbcd3ca893a638eb5137e (diff) | |
download | scala-27f573afb47fcc38627df20058fae1cfa0fcb947.tar.gz scala-27f573afb47fcc38627df20058fae1cfa0fcb947.tar.bz2 scala-27f573afb47fcc38627df20058fae1cfa0fcb947.zip |
new starr, with some changes to varargs handling.
Diffstat (limited to 'src/compiler')
20 files changed, 139 insertions, 81 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 56b8253fa7..a27169503e 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -655,6 +655,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable */ class Run { +// settings.newArrays.value = true +// settings.print.value = List("era") + if (settings.verbose.value) println("compiling with newArrays = "+settings.newArrays.value) + var isDefined = false private val firstPhase = { diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index c4f0be7cf5..3922e3fd40 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -119,6 +119,10 @@ trait TreeDSL { def ===(rhs: Tree) = Assign(target, rhs) /** Methods for sequences **/ + //[Martin] I don't understand why the toSequence call is needed. + //It seems redundant. If you want a widening, a Typed (xxx: Sequence) + //would be more efficient. If you want to also deal with arrays, + //it's won't work like this, because arrays will lack the toSequence method. def DROP(count: Int): Tree = if (count == 0) target else (target DOT nme.drop)(LIT(count)) DOT nme.toSequence diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index edfca57be6..233a3368bd 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -273,8 +273,15 @@ abstract class TreeGen def mkModuleAccessDcl(accessor: Symbol) = DefDef(accessor setFlag lateDEFERRED, EmptyTree) - def mkRuntimeCall(meth: Name, args: List[Tree]): Tree = + def mkRuntimeCall(meth: Name, args: List[Tree]): Tree = { + assert(!settings.newArrays.value || meth.toString != "boxArray") Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args) + } + + // !!! todo: remove + def mkPredefCall(meth: Name, args: List[Tree]): Tree = { + Apply(Select(mkAttributedRef(PredefModule), meth), args) + } /** Make a synchronized block on 'monitor'. */ def mkSynchronized(monitor: Tree, body: Tree): Tree = @@ -285,7 +292,7 @@ abstract class TreeGen def paramToArg(vparam: Symbol) = { val arg = Ident(vparam) - if (vparam.tpe.typeSymbol == RepeatedParamClass) wildcardStar(arg) + if (isRepeatedParamType(vparam.tpe)) wildcardStar(arg) else arg } diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index 5e1a36dc72..a4f585b196 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -170,8 +170,10 @@ abstract class TreeInfo { /** Is type a of the form T* ? */ def isRepeatedParamType(tpt: Tree) = tpt match { - case AppliedTypeTree(Select(_, rp), _) => rp == nme.REPEATED_PARAM_CLASS_NAME.toTypeName - case TypeTree() => tpt.tpe.typeSymbol == definitions.RepeatedParamClass + case AppliedTypeTree(Select(_, rp), _) => + rp == nme.REPEATED_PARAM_CLASS_NAME.toTypeName || + rp == nme.JAVA_REPEATED_PARAM_CLASS_NAME.toTypeName + case TypeTree() => definitions.isRepeatedParamType(tpt.tpe) case _ => false } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 580331a3a7..2f8d6ae9f6 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -865,7 +865,8 @@ abstract class GenICode extends SubComponent { } else { ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos) if (tree.symbol == definitions.ArrayClass) - generatedType = REFERENCE(definitions.BoxedAnyArrayClass) + generatedType = REFERENCE( + if (settings.newArrays.value) definitions.ObjectClass else definitions.BoxedAnyArrayClass) else generatedType = REFERENCE(ctx.clazz.symbol) } diff --git a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala index d5a2704857..8e9f062fa7 100644 --- a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala +++ b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala @@ -57,7 +57,7 @@ trait ModelToXML extends ModelExtractor { if (definitions.isFunctionType(tpe)) { val (args,r) = tpe.normalize.typeArgs.splitAt(tpe.normalize.typeArgs.length - 1); args.mkXML("(", ", ", ")")(link) ++ Text(" => ") ++ link(r.head); - } else if (tpe.typeSymbol == definitions.RepeatedParamClass) { + } else if (definitions.isRepeatedParamType(tpe)) { assert(tpe.typeArgs.length == 1) link(tpe.typeArgs(0)) ++ Text("*") } else if (tpe.typeSymbol == definitions.ByNameParamClass) { diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 450ace6124..4d36816853 100755 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -480,7 +480,7 @@ trait JavaParsers extends JavaScanners { if (in.token == DOTDOTDOT) { in.nextToken t = atPos(t.pos) { - AppliedTypeTree(scalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t)) + AppliedTypeTree(scalaDot(nme.JAVA_REPEATED_PARAM_CLASS_NAME.toTypeName), List(t)) } } varDecl(in.currentPos, Modifiers(Flags.JAVA | Flags.PARAM), t, ident()) diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 1880707c70..7d624d8289 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -133,6 +133,16 @@ trait Definitions { nme.REPEATED_PARAM_CLASS_NAME, tparam => seqType(tparam.typeConstructor) ) + + lazy val JavaRepeatedParamClass = newCovariantPolyClass( + ScalaPackageClass, + nme.JAVA_REPEATED_PARAM_CLASS_NAME, + tparam => arrayType(tparam.typeConstructor) + ) + + def isRepeatedParamType(tp: Type) = + tp.typeSymbol == RepeatedParamClass || tp.typeSymbol == JavaRepeatedParamClass + lazy val ByNameParamClass = newCovariantPolyClass( ScalaPackageClass, nme.BYNAME_PARAM_CLASS_NAME, @@ -282,6 +292,7 @@ trait Definitions { } def seqType(arg: Type) = typeRef(SeqClass.typeConstructor.prefix, SeqClass, List(arg)) + def arrayType(arg: Type) = typeRef(ArrayClass.typeConstructor.prefix, ArrayClass, List(arg)) // // .NET backend @@ -666,12 +677,13 @@ trait Definitions { def isNumericValueClass(sym: Symbol): Boolean = (sym ne BooleanClass) && (boxedClass contains sym) + // !!! todo comment & rename! def isValueType(sym: Symbol) = isValueClass(sym) || unboxMethod.contains(sym) /** Is symbol a value or array class? */ def isUnboxedClass(sym: Symbol): Boolean = - isValueType(sym) || sym == ArrayClass + isValueType(sym) || !settings.newArrays.value && sym == ArrayClass def signature(tp: Type): String = { def erasure(tp: Type): Type = tp match { @@ -740,8 +752,8 @@ trait Definitions { StringClass, "+", anyparam, StringClass.typeConstructor) setFlag FINAL // #2264 - val tmp = AnnotationDefaultAttr - + var tmp = AnnotationDefaultAttr + tmp = RepeatedParamClass // force initalization if (forMSIL) { val intType = IntClass.typeConstructor val intParam = List(intType) @@ -781,8 +793,7 @@ trait Definitions { newMethod(StringClass, "trim", List(), stringType) newMethod(StringClass, "intern", List(), stringType) newMethod(StringClass, "replace", List(charType, charType), stringType) - newMethod(StringClass, "toCharArray", List(), - appliedType(ArrayClass.typeConstructor, List(charType))) + newMethod(StringClass, "toCharArray", List(), arrayType(charType)) } } //init diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index 410cc75b67..94fc787e76 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -197,6 +197,7 @@ trait StdNames { val ROOT = newTermName("<root>") val ROOTPKG = newTermName("_root_") val REPEATED_PARAM_CLASS_NAME = newTermName("<repeated>") + val JAVA_REPEATED_PARAM_CLASS_NAME = newTermName("<repeated...>") val BYNAME_PARAM_CLASS_NAME = newTermName("<byname>") val EQUALS_PATTERN_NAME = newTermName("<equals>") val SELF = newTermName("$this") @@ -312,6 +313,7 @@ trait StdNames { val map = newTermName("map") val Mutable = newTypeName("Mutable") val ne = newTermName("ne") + val newArray = newTermName("newArray") val next = newTermName("next") val notify_ = newTermName("notify") val notifyAll_ = newTermName("notifyAll") diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 3816b89e59..ab7dd877c7 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -536,7 +536,8 @@ abstract class ClassfileParser { } } - /** Convert repeated parameters to arrays if they occur as part of a Java method + /** Convert array parameters denoting a repeated parameter of a Java method + * to JavaRepeatedParamClass types. */ private def arrayToRepeated(tp: Type): Type = tp match { case MethodType(params, rtpe) => @@ -544,7 +545,7 @@ abstract class ClassfileParser { assert(formals.last.typeSymbol == definitions.ArrayClass) val method = params.last.owner val newParams = method.newSyntheticValueParams(formals.init ::: - List(appliedType(definitions.RepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head)))) + List(appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head)))) MethodType(newParams, rtpe) case PolyType(tparams, rtpe) => PolyType(tparams, arrayToRepeated(rtpe)) diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 47e62a05fe..45acc4f763 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -338,6 +338,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } def boxArray(t: Tree) = { + assert(!settings.newArrays.value) val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe BLOCK( VAL(sym) === t, diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index d443cbdc70..0efd87a0ac 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -51,6 +51,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. 0 } + def isTopLevelGenericArray(tp: Type): Boolean = genericArrayLevel(tp) == 1 + /** <p> * The erasure <code>|T|</code> of a type <code>T</code>. This is: * </p> @@ -103,7 +105,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. } if (sym == ArrayClass) if (!settings.newArrays.value && isGeneric(tp)) erasedTypeRef(BoxedArrayClass) - else if (settings.newArrays.value && genericArrayLevel(tp) == 1) ObjectClass.tpe + else if (settings.newArrays.value && isTopLevelGenericArray(tp)) ObjectClass.tpe else typeRef(apply(pre), sym, args map this) else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass) erasedTypeRef(ObjectClass) else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) @@ -603,8 +605,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List())) else */ - if (isValueType(targClass) || - (targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass))) { + if (isValueType(targClass)) { + unbox(qual1, targ.tpe) + } else if (targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass)) { assert(!settings.newArrays.value) unbox(qual1, targ.tpe) } else if (!settings.newArrays.value && targClass == ArrayClass && qualClass == ObjectClass || isSeqClass(targClass)) { @@ -623,28 +626,24 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name)))) else { var qual1 = typedQualifier(qual); - if (tree.symbol.owner == ArrayClass && qual1.tpe.typeSymbol == AnyRefClass && settings.newArrays.value) { - typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, List(qual)) } - } else { - if ((isValueType(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol)) || - (qual1.tpe.typeSymbol == ArrayClass && !isUnboxedArrayMember(tree.symbol) && !settings.newArrays.value)) - qual1 = box(qual1); - else if (!isValueType(qual1.tpe.typeSymbol) && isUnboxedValueMember(tree.symbol)) - qual1 = unbox(qual1, tree.symbol.owner.tpe) - else if (tree.symbol.owner == ArrayClass && (BoxedArrayClass isSubClass qual1.tpe.typeSymbol) && !settings.newArrays.value) - qual1 = cast(qual1, BoxedArrayClass.tpe) + if ((isValueType(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol)) || + (qual1.tpe.typeSymbol == ArrayClass && !isUnboxedArrayMember(tree.symbol) && !settings.newArrays.value)) + qual1 = box(qual1); + else if (!isValueType(qual1.tpe.typeSymbol) && isUnboxedValueMember(tree.symbol)) + qual1 = unbox(qual1, tree.symbol.owner.tpe) + else if (tree.symbol.owner == ArrayClass && (BoxedArrayClass isSubClass qual1.tpe.typeSymbol) && !settings.newArrays.value) + qual1 = cast(qual1, BoxedArrayClass.tpe) - if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.typeSymbol)) - tree.symbol = NoSymbol - else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.paramTypes.isEmpty) { - assert(qual1.symbol.isStable, qual1.symbol); - qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType - } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) { - // println("member cast "+tree.symbol+" "+tree.symbol.ownerChain+" "+qual1+" "+qual1.tpe) - qual1 = cast(qual1, tree.symbol.owner.tpe) - } - treeCopy.Select(tree, qual1, name) + if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.typeSymbol)) + tree.symbol = NoSymbol + else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.paramTypes.isEmpty) { + assert(qual1.symbol.isStable, qual1.symbol); + qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType + } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) { + // println("member cast "+tree.symbol+" "+tree.symbol.ownerChain+" "+qual1+" "+qual1.tpe) + qual1 = cast(qual1, tree.symbol.owner.tpe) } + treeCopy.Select(tree, qual1, name) } case _ => tree @@ -969,6 +968,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. fun.symbol != Object_isInstanceOf) => // leave all other type tests/type casts, remove all other type applications fun + case Apply(fn @ Select(qual, name), args) + if (settings.newArrays.value && fn.symbol.owner == ArrayClass && isTopLevelGenericArray(qual.tpe.widen)) => + // convert calls to apply/update/length on generic arrays to + // calls of ScalaRunTime.array_xxx method calls + typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, qual :: args) } case Apply(fn, args) => if (!settings.newArrays.value) { def isGenericArray(tpe: Type): Boolean = erasure(tpe).typeSymbol == BoxedArrayClass diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 9f1897353e..e10a8d8365 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -22,7 +22,8 @@ import scala.tools.nsc.util.Position * - for every argument to a def parameter `x: => T': * if argument is not a reference to a def parameter: * convert argument `e' to (expansion of) `() => e' - * - for every repeated parameter `x: T*' --> x: Seq[T]. + * - for every repeated Scala parameter `x: T*' --> x: Seq[T]. + * - for every repeated Java parameter `x: T*' --> x: Array[T]. * - for every argument list that corresponds to a repeated parameter * (a_1, ..., a_n) => (Seq(a_1, ..., a_n)) * - for every argument list that is an escaped sequence @@ -67,6 +68,8 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { apply(functionType(List(), arg)) case TypeRef(pre, sym, args) if (sym == RepeatedParamClass) => apply(appliedType(SeqClass.typeConstructor, args)) + case TypeRef(pre, sym, args) if (sym == JavaRepeatedParamClass) => + apply(appliedType(ArrayClass.typeConstructor, args)) case _ => expandAlias(mapOver(tp)) } @@ -89,31 +92,13 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { } } - /** Convert repeated parameters to arrays if they occur as part of a Java method - */ - private def repeatedToArray(tp: Type): Type = tp match { - case MethodType(params, rtpe) - if (!params.isEmpty && params.last.tpe.typeSymbol == RepeatedParamClass) => - val arrayParam = params.last.owner.newSyntheticValueParams(List( - appliedType(ArrayClass.typeConstructor, List(params.last.tpe.typeArgs.head)))) - MethodType(params.init ::: arrayParam, rtpe) - case PolyType(tparams, rtpe) => - val rtpe1 = repeatedToArray(rtpe) - if (rtpe1 eq rtpe) tp - else PolyType(tparams, rtpe1) - case _ => - tp - } - /** - return symbol's transformed type, * - if symbol is a def parameter with transformed type T, return () => T * * @MAT: starting with this phase, the info of every symbol will be normalized */ def transformInfo(sym: Symbol, tp: Type): Type = - if (sym.isType) uncurryType(tp) - else if (sym.isMethod && sym.hasFlag(JAVA)) uncurry(repeatedToArray(tp)) - else uncurry(tp) + if (sym.isType) uncurryType(tp) else uncurry(tp) /** Traverse tree omitting local method definitions. * If a `return' is encountered, set `returnFound' to true. @@ -374,8 +359,10 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { def transformArgs(pos: Position, args: List[Tree], formals: List[Type], isJava: Boolean) = { val args1 = formals.lastOption match { - case Some(TypeRef(pre, sym, List(elempt))) if (sym == RepeatedParamClass) => + case Some(lastFormal) if isRepeatedParamType(lastFormal) => + def callMethod(tree: Tree, nme: Name): Tree = { + assert(!settings.newArrays.value) val sym = tree.tpe member nme assert(sym != NoSymbol) val arguments = @@ -389,17 +376,41 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { } def mkArrayValue(ts: List[Tree]) = { - val arr = ArrayValue(TypeTree(elempt), ts) setType formals.last + val elemTp = lastFormal.typeArgs.head + val arr = ArrayValue(TypeTree(elemTp), ts) setType arrayType(elemTp) if (isJava || inPattern) arr + else if (settings.newArrays.value) + atPhase(phase.next) { + localTyper.typedPos(pos) { + val predef = gen.mkAttributedRef(PredefModule) + val meth = + if ((elemTp <:< AnyRefClass.tpe) || isValueClass(elemTp.typeSymbol)) + Select(predef, "wrapArray") + else + TypeApply(Select(predef, "genericWrapArray"), List(TypeTree(elemTp))) + Apply(meth, List(arr)) + } + } else callMethod(arr, nme.toSequence) // println("need to callMethod("+arr+", nme.toSequence)"); arr } - } + } setType formals.last // when calling into java varargs, make sure it's an array - see bug #1360 def forceToArray(arg: Tree) = { val Typed(tree, _) = arg if (isJava && tree.tpe.typeSymbol != ArrayClass && - (tree.tpe.typeSymbol isSubClass TraversableClass)) callMethod(tree, nme.toArray) - else tree + (tree.tpe.typeSymbol isSubClass TraversableClass)) { + if (settings.newArrays.value) { + val toArraySym = tree.tpe member nme.toArray + assert(toArraySym != NoSymbol) + atPhase(phase.next) { + localTyper.typedPos(pos) { + Apply( + gen.mkAttributedSelect(tree, toArraySym), + List(localTyper.getManifestTree(tree.pos, tree.tpe.typeArgs.head, false))) + } + } + } else callMethod(tree, nme.toArray) + } else tree } if (args.isEmpty) diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index 5f123ffa06..7d75994ef3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -76,6 +76,7 @@ trait EtaExpansion { self: Analyzer => if (treeInfo.isPureExpr(tree)) tree else { val vname: Name = freshName(tree.pos, 0) + // Problem with ticket #2351 here defs += atPos(tree.pos) { ValDef(Modifiers(SYNTHETIC), vname, TypeTree(), tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 96670ab131..dbc90e569b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -743,7 +743,7 @@ self: Analyzer => val timer3 = System.nanoTime() if (result == SearchFailure) manifFail += timer3 - timer2 else manifSucceed += timer3 - timer2 if (result == SearchFailure && settings.debug.value) - println("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+parts(pt)+implicitsOfExpectedType) + log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+parts(pt)+implicitsOfExpectedType) implicitTime += System.nanoTime() - start result } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index a6c1cf744b..20f6a1ff45 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -33,8 +33,7 @@ trait Infer { private def assertNonCyclic(tvar: TypeVar) = assert(tvar.constr.inst != tvar, tvar.origin) - def isVarArgs(formals: List[Type]) = - !formals.isEmpty && (formals.last.typeSymbol == RepeatedParamClass) + def isVarArgs(formals: List[Type]) = !formals.isEmpty && isRepeatedParamType(formals.last) /** The formal parameter types corresponding to <code>formals</code>. * If <code>formals</code> has a repeated last parameter, a list of @@ -575,6 +574,8 @@ trait Infer { tparam.tpe } else if (targ.typeSymbol == RepeatedParamClass) { targ.baseType(SeqClass) + } else if (targ.typeSymbol == JavaRepeatedParamClass) { + targ.baseType(ArrayClass) } else { targ.widen } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 3dec50e03d..7cca32a779 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -832,8 +832,7 @@ abstract class RefChecks extends InfoTransform { def isRepeatedParamArg(tree: Tree) = currentApplication match { case Apply(fn, args) => !args.isEmpty && (args.last eq tree) && - fn.tpe.paramTypes.length == args.length && - fn.tpe.paramTypes.last.typeSymbol == RepeatedParamClass + fn.tpe.paramTypes.length == args.length && isRepeatedParamType(fn.tpe.paramTypes.last) case _ => false } diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index c5976a6f3f..5001f8b9bf 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -336,7 +336,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT if (sym.isSubClass(ownerClass)) true else false case _ => false } - if (v.info.typeSymbol == definitions.RepeatedParamClass) { + if (definitions.isRepeatedParamType(v.info)) { res = gen.wildcardStar(res) log("adapted to wildcard star: " + res) } diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index d1a746f222..a1c1a7b661 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -172,8 +172,8 @@ trait SyntheticMethods extends ast.TreeDSL { def makeTrees(acc: Symbol, cpt: Type): (Tree, Bind) = { val varName = context.unit.fresh.newName(clazz.pos.focus, acc.name + "$") val (eqMethod, binding) = - if (cpt.isVarargs) (nme.sameElements, Star(WILD())) - else (nme.EQ , WILD() ) + if (isRepeatedParamType(cpt)) (nme.sameElements, Star(WILD())) + else (nme.EQ , WILD() ) ((varName DOT eqMethod)(Ident(acc)), varName BIND binding) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d936941224..2d519f8da8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -397,7 +397,7 @@ trait Typers { self: Analyzer => /* if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1) error(pos, "methods with `=>'-parameter can be converted to function values only if they take no other parameters") - if (formals exists (_.typeSymbol == RepeatedParamClass)) + if (formals exists (isRepeatedParamType(_))) error(pos, "methods with `*'-parameters cannot be converted to function values"); */ if (restpe.isDependent) @@ -913,7 +913,7 @@ trait Typers { self: Analyzer => case _ => false } - if (isStructuralType(pt) && tree.tpe.typeSymbol == ArrayClass) { + if (isStructuralType(pt) && tree.tpe.typeSymbol == ArrayClass && !settings.newArrays.value) { // all Arrays used as structural refinement typed values must be boxed // this does not solve the case where the type to be adapted to comes // from a type variable that was bound by a strctural but is instantiated @@ -1449,7 +1449,7 @@ trait Typers { self: Analyzer => case Apply(fn, args) => val (superConstr, args1) = decompose(fn) val formals = fn.tpe.paramTypes - val args2 = if (formals.isEmpty || formals.last.typeSymbol != RepeatedParamClass) args + val args2 = if (formals.isEmpty || !isRepeatedParamType(formals.last)) args else args.take(formals.length - 1) ::: List(EmptyTree) if (args2.length != formals.length) assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug @@ -1522,7 +1522,7 @@ trait Typers { self: Analyzer => val tparams1 = ddef.tparams mapConserve typedTypeDef val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef) for (vparams1 <- vparamss1; if !vparams1.isEmpty; vparam1 <- vparams1.init) { - if (vparam1.symbol.tpe.typeSymbol == RepeatedParamClass) + if (isRepeatedParamType(vparam1.symbol.tpe)) error(vparam1.pos, "*-parameter must come last") } var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt)) @@ -1577,10 +1577,7 @@ trait Typers { self: Analyzer => } } - if (meth.paramss.exists( ps => { - ps.exists(_.hasFlag(DEFAULTPARAM)) && - (ps.last.tpe.typeSymbol == RepeatedParamClass) - })) + if (meth.paramss.exists(ps => ps.exists(_.hasFlag(DEFAULTPARAM)) && isRepeatedParamType(ps.last.tpe))) error(meth.pos, "a parameter section with a `*'-parameter is not allowed to have default arguments") } @@ -3660,7 +3657,18 @@ trait Typers { self: Analyzer => typed1(atPos(tree.pos)(Block(stats, Apply(expr, args))), mode, pt) case Apply(fun, args) => - typedApply(fun, args) + typedApply(fun, args) match { + case Apply(Select(New(tpt), name), args) + if (settings.newArrays.value && tpt.tpe.typeSymbol == ArrayClass && args.length == 1 && erasure.isTopLevelGenericArray(tpt.tpe)) => + // convert new Array[T](len) to evidence[ClassManifest[T]].newArray(len) + val newArrayApp = atPos(tree.pos) { + val manif = getManifestTree(tree.pos, tpt.tpe.typeArgs.head, false) + Apply(Select(manif, nme.newArray), args) + } + typed(newArrayApp, mode, pt) + case tree1 => + tree1 + } case ApplyDynamic(qual, args) => val reflectiveCalls = !(settings.refinementMethodDispatch.value == "invoke-dynamic") @@ -3884,16 +3892,17 @@ trait Typers { self: Analyzer => case None => typed(tree, pt) } - def findManifest(tp: Type, full: Boolean) = + def findManifest(tp: Type, full: Boolean) = atPhase(currentRun.typerPhase) { inferImplicit( EmptyTree, appliedType((if (full) FullManifestClass else PartialManifestClass).typeConstructor, List(tp)), true, false, context) + } def getManifestTree(pos: Position, tp: Type, full: Boolean): Tree = { val manifestOpt = findManifest(tp, false) if (manifestOpt.tree.isEmpty) { - error(pos, "cannot find "+(if (full) "" else "class ")+"manifest for element type of "+tp) + error(pos, "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp) Literal(Constant(null)) } else { manifestOpt.tree |