diff options
author | Antonio Cunei <antonio.cunei@epfl.ch> | 2009-11-12 22:51:49 +0000 |
---|---|---|
committer | Antonio Cunei <antonio.cunei@epfl.ch> | 2009-11-12 22:51:49 +0000 |
commit | 2970a618827e4d12d334296958bac2c0b6cc80f6 (patch) | |
tree | 7a96eb939fc2fb5cabd200128a0c890e828a6648 /src/compiler | |
parent | a02f860355f188a43a27a341d9c7edb6cecd3e13 (diff) | |
download | scala-2970a618827e4d12d334296958bac2c0b6cc80f6.tar.gz scala-2970a618827e4d12d334296958bac2c0b6cc80f6.tar.bz2 scala-2970a618827e4d12d334296958bac2c0b6cc80f6.zip |
Merged revisions 19598-19601,19604 via svnmerge...
Merged revisions 19598-19601,19604 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk
........
r19598 | moors | 2009-11-12 22:04:25 +0100 (Thu, 12 Nov 2009) | 1 line
documentation for fix of #2482
........
r19599 | moors | 2009-11-12 22:04:26 +0100 (Thu, 12 Nov 2009) | 1 line
Merge branch 'ticket/2594'
........
r19600 | extempore | 2009-11-12 22:39:12 +0100 (Thu, 12 Nov 2009) | 2 lines
Removed everything deprecated in 2.7.3 or earlier except the lower
case primitive type aliases, plus associated fixes. ........ r19601 |
extempore | 2009-11-12 22:39:26 +0100 (Thu, 12 Nov 2009) | 2 lines
Moved those bits of Predef into the scala package object which would
go without a fight. ........ r19604 | extempore | 2009-11-12 23:13:04
+0100 (Thu, 12 Nov 2009) | 4 lines
Bringing BigInt and BigDecimal into the club of things which can
be equal to one another and which will have the same hashCode. Fixed
some old and some new bugs associated with equality. Note: not fully
optimized. ........
Diffstat (limited to 'src/compiler')
4 files changed, 59 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index e1ddd260cb..f0c44bb227 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -1410,24 +1410,32 @@ abstract class GenICode extends SubComponent { * When it is statically known that both sides are equal and subtypes of Number of Character, * not using the rich equality is possible (their own equals method will do ok.)*/ def mustUseAnyComparator: Boolean = { + import definitions._ + + /** The various ways a boxed primitive might materialize at runtime. */ + def isJavaBoxed(sym: Symbol) = + (sym == ObjectClass) || + (sym == SerializableClass) || + (sym == ComparableClass) || + (sym isNonBottomSubClass BoxedNumberClass) || + (sym isNonBottomSubClass BoxedCharacterClass) + def isBoxed(sym: Symbol): Boolean = - ((sym isNonBottomSubClass definitions.BoxedNumberClass) || - (!forMSIL && (sym isNonBottomSubClass definitions.BoxedCharacterClass))) - - val lsym = l.tpe.typeSymbol - val rsym = r.tpe.typeSymbol - (lsym == ObjectClass) || - (rsym == ObjectClass) || - (lsym != rsym) && (isBoxed(lsym) || isBoxed(rsym)) + if (forMSIL) (sym isNonBottomSubClass BoxedNumberClass) + else isJavaBoxed(sym) + + isBoxed(l.tpe.typeSymbol) && isBoxed(r.tpe.typeSymbol) } if (mustUseAnyComparator) { - var equalsMethod = BoxesRunTime_equals // when -optimise is on we call the @inline-version of equals, found in ScalaRunTime - if (settings.XO.value) { - equalsMethod = definitions.getMember(definitions.ScalaRunTimeModule, nme.inlinedEquals) - ctx.bb.emit(LOAD_MODULE(definitions.ScalaRunTimeModule)) - } + val equalsMethod = + if (!settings.XO.value) BoxesRunTime_equals + else { + ctx.bb.emit(LOAD_MODULE(definitions.ScalaRunTimeModule)) + definitions.getMember(definitions.ScalaRunTimeModule, nme.inlinedEquals) + } + val ctx1 = genLoad(l, ctx, ANY_REF_CLASS) val ctx2 = genLoad(r, ctx1, ANY_REF_CLASS) ctx2.bb.emit(CALL_METHOD(equalsMethod, if (settings.XO.value) Dynamic else Static(false))) diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index a3cc5310ab..8ed2b04045 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -237,7 +237,7 @@ trait TypeKinds { self: ICodes => // override def maxType(other: TypeKind): TypeKind = other match { // case STRING => STRING; // case _ => - // abort("Uncomparbale type kinds: STRING with " + other); + // abort("Uncomparable type kinds: STRING with " + other); // } // } @@ -263,7 +263,7 @@ trait TypeKinds { self: ICodes => case REFERENCE(_) | ARRAY(_) => REFERENCE(AnyRefClass) case _ => - abort("Uncomparbale type kinds: REFERENCE with " + other) + abort("Uncomparable type kinds: REFERENCE with " + other) } /** Checks subtyping relationship. */ @@ -334,7 +334,7 @@ trait TypeKinds { self: ICodes => if (elem == elem2) ARRAY(elem) else REFERENCE(AnyRefClass) case _ => - abort("Uncomparbale type kinds: ARRAY with " + other) + abort("Uncomparable type kinds: ARRAY with " + other) } /** Array subtyping is covariant, as in Java. Necessary for checking @@ -370,7 +370,7 @@ trait TypeKinds { self: ICodes => case REFERENCE(_) | ARRAY(_) | BOXED(_) => REFERENCE(AnyRefClass) case _ => - abort("Uncomparbale type kinds: ARRAY with " + other) + abort("Uncomparable type kinds: ARRAY with " + other) } /** Checks subtyping relationship. */ @@ -409,7 +409,7 @@ trait TypeKinds { self: ICodes => case REFERENCE(_) => REFERENCE(AnyRefClass) case _ => - abort("Uncomparbale type kinds: ConcatClass with " + other) + abort("Uncomparable type kinds: ConcatClass with " + other) } /** Checks subtyping relationship. */ diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 2d1855dc84..84b08f1258 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -67,6 +67,7 @@ abstract class Pickler extends SubComponent { private var ep = 0 private val index = new LinkedHashMap[AnyRef, Int] + // collect higher-order type params private var locals: Set[Symbol] = Set() // private var boundSyms: List[Symbol] = Nil @@ -80,16 +81,16 @@ abstract class Pickler extends SubComponent { else sym.owner /** Is root in symbol.owner*, or should it be treated as a local symbol - * anyway? This is the case if symbol is a refinement class or - * an existentially bound variable. + * anyway? This is the case if symbol is a refinement class, + * an existentially bound variable, or a higher-order type parameter. */ private def isLocal(sym: Symbol): Boolean = !sym.isPackageClass && (sym.name.toTermName == rootName && sym.owner == rootOwner || sym != NoSymbol && isLocal(sym.owner) || sym.isRefinementClass || - sym.isAbstractType && sym.hasFlag(EXISTENTIAL) || - (locals contains sym)) + sym.isAbstractType && sym.hasFlag(EXISTENTIAL) || // existential param + (locals contains sym)) // higher-order type param private def staticAnnotations(annots: List[AnnotationInfo]) = annots filter(ann => @@ -191,11 +192,11 @@ abstract class Pickler extends SubComponent { putType(restpe); putSymbols(params) case PolyType(tparams, restpe) => tparams foreach { tparam => - if (!isLocal(tparam)) locals += tparam + if (!isLocal(tparam)) locals += tparam // similar to existential types, these tparams are local } putType(restpe); putSymbols(tparams) case ExistentialType(tparams, restpe) => -// val savedBoundSyms = boundSyms +// val savedBoundSyms = boundSyms // boundSyms are known to be local based on the EXISTENTIAL flag (see isLocal) // boundSyms = tparams ::: boundSyms // try { putType(restpe); diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index eec523a2b8..67c963acf5 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -47,9 +47,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { // ------ Type transformation -------------------------------------------------------- -//@MAT: uncurry and uncurryType fully expand type aliases in their input and output -// note: don't normalize higher-kined types -- @M TODO: maybe split those uses of normalize? -// OTOH, should be a problem as calls to normalize only occur on types with kind * in principle (in well-typed programs) +// uncurry and uncurryType expand type aliases private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp private def isUnboundedGeneric(tp: Type) = tp match { @@ -68,9 +66,9 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { tp0 case mt: ImplicitMethodType => apply(MethodType(mt.params, mt.resultType)) - case PolyType(List(), restpe) => + case PolyType(List(), restpe) => // nullary method type apply(MethodType(List(), restpe)) - case PolyType(tparams, restpe) => + case PolyType(tparams, restpe) => // polymorphic nullary method type, since it didn't occur in a higher-kinded position PolyType(tparams, apply(MethodType(List(), restpe))) case TypeRef(pre, ByNameParamClass, List(arg)) => apply(functionType(List(), arg)) @@ -83,6 +81,29 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { expandAlias(mapOver(tp)) } } + +//@M TODO: better fix for the gross hack that conflates polymorphic nullary method types with type functions +// `[tpars] tref` (PolyType(tpars, tref)) could uncurry to either: +// - `[tpars]() tref` (PolyType(tpars, MethodType(List(), tref)) +// a nullary method types uncurry to a method with an empty argument list +// - `[tpars] tref` (PolyType(tpars, tref)) +// a proper type function -- see mapOverArgs: can only occur in args of TypeRef (right?)) +// the issue comes up when a partial type application gets normalised to a polytype, like `[A] Function1[X, A]` +// should not apply the uncurry transform to such a type +// see #2594 for an example + + // decide whether PolyType represents a nullary method type (only if type has kind *) + // for higher-kinded types, leave PolyType intact + override def mapOverArgs(args: List[Type], tparams: List[Symbol]): List[Type] = + map2Conserve(args, tparams) { (arg, tparam) => + arg match { + // is this a higher-kinded position? (TODO: confirm this is the only case) + case PolyType(tparams, restpe) if tparam.typeParams.nonEmpty => // higher-kinded type param + PolyType(tparams, apply(restpe)) // could not be a nullary method type + case _ => + this(arg) + } + } } private val uncurryType = new TypeMap { |