summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2009-11-12 22:51:49 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2009-11-12 22:51:49 +0000
commit2970a618827e4d12d334296958bac2c0b6cc80f6 (patch)
tree7a96eb939fc2fb5cabd200128a0c890e828a6648 /src/compiler
parenta02f860355f188a43a27a341d9c7edb6cecd3e13 (diff)
downloadscala-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')
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala34
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala13
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala31
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 {