diff options
author | Martin Odersky <odersky@gmail.com> | 2009-11-12 16:12:16 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-11-12 16:12:16 +0000 |
commit | 9ed068ec0091c0f4f9dee0539540408d89e96776 (patch) | |
tree | c6db8b9755360ba6536c3a23eafa12e45b50e3d9 /src | |
parent | 39fb348121e43dd3d48b378f43a68ed8fc5fc157 (diff) | |
download | scala-9ed068ec0091c0f4f9dee0539540408d89e96776.tar.gz scala-9ed068ec0091c0f4f9dee0539540408d89e96776.tar.bz2 scala-9ed068ec0091c0f4f9dee0539540408d89e96776.zip |
Fixed #2517
Fixed #2606
Fixed #2598
Fixed #1836
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Constants.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 25 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 12 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 18 |
4 files changed, 51 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Constants.scala b/src/compiler/scala/tools/nsc/symtab/Constants.scala index 2a4d3e1fa1..53ada529e1 100644 --- a/src/compiler/scala/tools/nsc/symtab/Constants.scala +++ b/src/compiler/scala/tools/nsc/symtab/Constants.scala @@ -80,7 +80,15 @@ trait Constants { * @return ... */ override def equals(other: Any): Boolean = other match { - case that: Constant => this.tag == that.tag && this.value == that.value + case that: Constant => + this.tag == that.tag && + (this.value == that.value || isNaN(this.value) && isNaN(that.value)) + case _ => false + } + + def isNaN(value: Any) = value match { + case f: Float => f.isNaN + case d: Double => d.isNaN case _ => false } diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 1c22a6fdaf..579696feae 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -284,9 +284,9 @@ trait Symbols { newSyntheticValueParams(List(argtype)).head /** Type skolems are type parameters ``seen from the inside'' - * Given a class C[T] - * Then the class has a TypeParameter with name `T' in its typeParams list - * While type checking the class, there's a local copy of `T' which is a TypeSkolem + * Assuming a polymorpphic method m[T], its type is a PolyType which has a TypeParameter + * with name `T' in its typeParams list. While type checking the parameters, result type and + * body of the method, there's a local copy of `T' which is a TypeSkolem. */ final def newTypeSkolem: Symbol = new TypeSkolem(owner, pos, name, this) @@ -1813,7 +1813,19 @@ trait Symbols { if (util.Statistics.enabled) typeSymbolCount = typeSymbolCount + 1 } - /** A class for type parameters viewed from inside their scopes */ + /** A class for type parameters viewed from inside their scopes + * + * @param origin Can be either a tree, or a symbol, or null. + * If skolem got created from newTypeSkolem (called in Namers), origin denotes + * the type parameter from which the skolem was created. If it got created from + * skolemizeExistential, origin is either null or a Tree. If it is a Tree, it indicates + * where the skolem was introduced (this is important for knowing when to pack it + * again into ab Existential). origin is `null' only in skolemizeExistentials called + * from <:< or isAsSpecific, because here its value does not matter. + * I elieve the following invariant holds: + * + * origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL) + */ class TypeSkolem(initOwner: Symbol, initPos: Position, initName: Name, origin: AnyRef) extends TypeSymbol(initOwner, initPos, initName) { @@ -1822,11 +1834,16 @@ trait Symbols { val level = skolemizationLevel override def isSkolem = true + + /** If typeskolem comes from a type parameter, that parameter, otherwise skolem itself */ override def deSkolemize = origin match { case s: Symbol => s case _ => this } + + /** If type skolem comes from an existential, the tree where it was created */ override def unpackLocation = origin + override def typeParams = info.typeParams //@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo override def cloneSymbolImpl(owner: Symbol): Symbol = diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 676f19205a..6840f4ac4c 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -391,8 +391,18 @@ trait Types { */ def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type = this.subst(formals, actuals) + /** If this type is an existential, turn all existentially bound variables to type skolems. + * @param owner The owner of the created type skolems + * @param origin The tree whose type was an existential for which the skolem was created. + */ def skolemizeExistential(owner: Symbol, origin: AnyRef): Type = this + + /** A simple version of skolemizeExistential for situations where + * owner or unpack location do not matter (typically used in subtype tests) + */ + def skolemizeExistential: Type = skolemizeExistential(NoSymbol, null) + /** Reduce to beta eta-long normal form. Expands type aliases and converts higher-kinded TypeRef's to PolyTypes. @M */ def normalize = this // @MAT @@ -4065,7 +4075,7 @@ A type's typeSymbol should never be inspected directly. case ExistentialType(_, _) => try { skolemizationLevel += 1 - tp1.skolemizeExistential(NoSymbol, null) <:< tp2 + tp1.skolemizeExistential <:< tp2 } finally { skolemizationLevel -= 1 } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 8ed799ed60..898ad238a1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -884,7 +884,8 @@ trait Infer { case OverloadedType(pre, alts) => alts exists (alt => isAsSpecific(pre.memberType(alt), ftpe2)) case et: ExistentialType => - et.withTypeVars(isAsSpecific(_, ftpe2)) + isAsSpecific(ftpe1.skolemizeExistential, ftpe2) + //et.withTypeVars(isAsSpecific(_, ftpe2)) case mt: ImplicitMethodType => isAsSpecific(ftpe1.resultType, ftpe2) case MethodType(params @ (x :: xs), _) => @@ -1380,8 +1381,8 @@ trait Infer { } def checkCheckable(pos: Position, tp: Type, kind: String) { - def patternWarning(tp: Type, prefix: String) = { - context.unit.uncheckedWarning(pos, prefix+tp+" in type"+kind+" is unchecked since it is eliminated by erasure") + def patternWarning(tp0: Type, prefix: String) = { + context.unit.uncheckedWarning(pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure") } def check(tp: Type, bound: List[Symbol]) { def isLocalBinding(sym: Symbol) = @@ -1395,13 +1396,13 @@ trait Infer { case SingleType(pre, _) => check(pre, bound) case TypeRef(pre, sym, args) => - if (sym.isAbstractType) + if (sym.isAbstractType) { if (!isLocalBinding(sym)) patternWarning(tp, "abstract type ") - else if (sym.isAliasType) + } else if (sym.isAliasType) { check(tp.normalize, bound) - else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) + } else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) { error(pos, "type "+tp+" cannot be used in a type pattern or isInstanceOf test") - else + } else { for (arg <- args) { if (sym == ArrayClass) check(arg, bound) else arg match { @@ -1411,6 +1412,7 @@ trait Infer { patternWarning(arg, "non variable type-argument ") } } + } check(pre, bound) case RefinedType(parents, decls) => if (decls.isEmpty) for (p <- parents) check(p, bound) @@ -1447,7 +1449,7 @@ trait Infer { def inferTypedPattern(pos: Position, pattp: Type, pt0: Type): Type = { val pt = widen(pt0) - checkCheckable(pos, pattp, " pattern") + checkCheckable(pos, pattp, "pattern ") if (!(pattp <:< pt)) { val tpparams = freeTypeParamsOfTerms.collect(pattp) if (settings.debug.value) log("free type params (1) = " + tpparams) |