summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2009-11-12 17:02:43 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2009-11-12 17:02:43 +0000
commitdf03c236d1802d27dcb97b54303affccebede18a (patch)
tree74fbbee2856aa003cb1781f6c4082767152f715f /src
parentc71cd0ef9a7e455e3a13526c2893d98b14582bbb (diff)
downloadscala-df03c236d1802d27dcb97b54303affccebede18a.tar.gz
scala-df03c236d1802d27dcb97b54303affccebede18a.tar.bz2
scala-df03c236d1802d27dcb97b54303affccebede18a.zip
Merged revisions 19567,19569-19570 via svnmerge...
Merged revisions 19567,19569-19570 via svnmerge from https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r19567 | odersky | 2009-11-12 17:12:16 +0100 (Thu, 12 Nov 2009) | 4 lines Fixed #2517 Fixed #2606 Fixed #2598 Fixed #1836 ........ r19569 | moors | 2009-11-12 17:56:31 +0100 (Thu, 12 Nov 2009) | 8 lines fixed #2587 two underlying problems: - isAsSpecific did not skolemize lower (left) type in subtyping check (instead used withTypeVar on left and right) - withTypeVars did not clone the symbols of the type params (so they were not fresh) (the second fix is not essential due to the first fix, it "improves correctness", but should check whether performance is not impacted too severely) applied martin's documentation diff ........ r19570 | moors | 2009-11-12 17:56:33 +0100 (Thu, 12 Nov 2009) | 1 line fixed #2454 ........
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Constants.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala68
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala121
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala43
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
7 files changed, 160 insertions, 87 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 0f59d9a3d9..5db78420ec 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -836,7 +836,6 @@ trait ScalacSettings {
val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignements")
val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.")
val Ytailrec = BooleanSetting ("-Ytailrecommend", "Alert methods which would be tail-recursive if private or final.")
- val YhigherKindedRaw = BooleanSetting ("-Yhigher-kinded-raw", "(temporary!) Treat raw Java types as higher-kinded types.")
val Yjenkins = BooleanSetting ("-Yjenkins-hashCodes", "Use jenkins hash algorithm for case class generated hashCodes.")
// Warnings
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..e4cbe159a1 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 polymorphic 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)
@@ -423,6 +423,7 @@ trait Symbols {
final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes
final def isModuleClass = isClass && hasFlag(MODULE)
+ final def isClassOfModule = isModuleClass || isClass && nme.isLocalName(name)
final def isPackageClass = isClass && hasFlag(PACKAGE)
final def isPackageObject = isModule && name == nme.PACKAGEkw && owner.isPackageClass
final def isPackageObjectClass = isModuleClass && name.toTermName == nme.PACKAGEkw && owner.isPackageClass
@@ -884,6 +885,48 @@ trait Symbols {
infos ne null
}
+ /** Modify term symbol's type so that a raw type C is converted to an existential C[_]
+ *
+ * This is done in checkAccessible and overriding checks in refchecks
+ * We can't do this on class loading because it would result in infinite cycles.
+ */
+ private var triedCooking: Boolean = false
+ final def cookJavaRawInfo() {
+ require(isTerm)
+ // println("cookJavaRawInfo: "+(rawname, triedCooking))
+
+ if(triedCooking) return else triedCooking = true // only try once...
+
+ def cook(sym: Symbol) {
+ require(sym hasFlag JAVA)
+ // @M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible
+ // object rawToExistentialInJava extends TypeMap {
+ // def apply(tp: Type): Type = tp match {
+ // // any symbol that occurs in a java sig, not just java symbols
+ // // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
+ // case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
+ // val eparams = typeParamsToExistentials(sym, sym.typeParams)
+ // existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
+ // case _ =>
+ // mapOver(tp)
+ // }
+ // }
+ val tpe1 = rawToExistential(sym.tpe)
+ // println("cooking: "+ sym +": "+ sym.tpe +" to "+ tpe1)
+ if (tpe1 ne sym.tpe) {
+ sym.setInfo(tpe1)
+ }
+ }
+
+ if (hasFlag(JAVA))
+ cook(this)
+ else if (hasFlag(OVERLOADED))
+ for (sym2 <- alternatives)
+ if (sym2 hasFlag JAVA)
+ cook(sym2)
+ }
+
+
/** The type constructor of a symbol is:
* For a type symbol, the type corresponding to the symbol itself,
* excluding parameters.
@@ -1813,7 +1856,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 +1877,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..6145c4a0d7 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -88,7 +88,7 @@ trait Types {
/** Decrement depth unless it is a don't care */
private final def decr(depth: Int) = if (depth == AnyDepth) AnyDepth else depth - 1
- private final val printLubs = false //@MDEBUG
+ private final val printLubs = false
/** The current skolemization level, needed for the algorithms
* in isSameType, isSubType that do constraint solving under a prefix
@@ -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
@@ -1590,12 +1600,11 @@ A type's typeSymbol should never be inspected directly.
override def typeConstructor = rawTypeRef(pre, sym, List())
- // (args.isEmpty && !typeParamsDirect.isEmpty) && !isRawType(this)
- // check for isRawType: otherwise raw types are considered higher-kinded types during subtyping:
- override def isHigherKinded
- = (args.isEmpty && !typeParamsDirect.isEmpty) && (settings.YhigherKindedRaw.value || !isRaw(sym, args))
- // (args.isEmpty && !typeParamsDirect.isEmpty) && (phase.erasedTypes || !sym.hasFlag(JAVA))
-
+ // a reference (in a Scala program) to a type that has type parameters, but where the reference does not include type arguments
+ // note that it doesn't matter whether the symbol refers to a java or scala symbol,
+ // it does matter whether it occurs in java or scala code
+ // typerefs w/o type params that occur in java signatures/code are considered raw types, and are represented as existential types
+ override def isHigherKinded = (args.isEmpty && !typeParamsDirect.isEmpty)
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
if (isHigherKinded) {
@@ -1952,13 +1961,12 @@ A type's typeSymbol should never be inspected directly.
def withTypeVars(op: Type => Boolean): Boolean = withTypeVars(op, AnyDepth)
def withTypeVars(op: Type => Boolean, depth: Int): Boolean = {
- val tvars = quantified map (tparam => TypeVar(tparam.tpe, new TypeConstraint)) // @M TODO
-//@M should probably change to handle HK type infer properly:
-// val tvars = quantified map (tparam => TypeVar(tparam))
- val underlying1 = underlying.instantiateTypeParams(quantified, tvars)
+ val quantifiedFresh = cloneSymbols(quantified)
+ val tvars = quantifiedFresh map (tparam => TypeVar(tparam))
+ val underlying1 = underlying.instantiateTypeParams(quantified, tvars) // fuse subst quantified -> quantifiedFresh -> tvars
op(underlying1) && {
- solve(tvars, quantified, quantified map (x => 0), false, depth) &&
- isWithinBounds(NoPrefix, NoSymbol, quantified, tvars map (_.constr.inst))
+ solve(tvars, quantifiedFresh, quantifiedFresh map (x => 0), false, depth) &&
+ isWithinBounds(NoPrefix, NoSymbol, quantifiedFresh, tvars map (_.constr.inst))
}
}
}
@@ -2010,7 +2018,7 @@ A type's typeSymbol should never be inspected directly.
* Not used after phase `typer'.
* A higher-kinded type variable has type arguments (a list of Type's) and type paramers (list of Symbols)
* A TypeVar whose list of args is non-empty can only be instantiated by a higher-kinded type that can be applied to these args
- * NOTE:
+ * a typevar is much like a typeref, except it has special logic for type equality/subtyping
*/
class TypeVar(val origin: Type, val constr0: TypeConstraint, override val typeArgs: List[Type], override val params: List[Symbol]) extends Type {
// params are needed to keep track of variance (see mapOverArgs in SubstMap)
@@ -2021,7 +2029,7 @@ A type's typeSymbol should never be inspected directly.
var constr = constr0
def instValid = constr.instValid
- /** The variable's skolemizatuon level */
+ /** The variable's skolemization level */
val level = skolemizationLevel
/**
@@ -2034,14 +2042,14 @@ A type's typeSymbol should never be inspected directly.
if(newArgs.isEmpty) this // SubstMap relies on this (though this check is redundant when called from appliedType...)
else TypeVar(origin, constr, newArgs, params) // @M TODO: interaction with undoLog??
// newArgs.length may differ from args.length (could've been empty before)
- // OBSOLETE BEHAVIOUR: imperatively update args to new args
- // this initialises a TypeVar's arguments to the arguments of the type
// example: when making new typevars, you start out with C[A], then you replace C by ?C, which should yield ?C[A], then A by ?A, ?C[?A]
- // thus, we need to track a TypeVar's arguments, and map over them (see TypeMap::mapOver)
- // OBSOLETE BECAUSE: can't update imperatively because TypeVars do get applied to different arguments over type (in asSeenFrom) -- see pos/tcpoly_infer_implicit_tuplewrapper.scala
- // CONSEQUENCE: make new TypeVar's for every application of a TV to args,
- // inference may generate several TypeVar's for a single type parameter that must be inferred,
- // one of them is in the set of tvars that need to be solved, and they all share the same constr instance
+ // we need to track a TypeVar's arguments, and map over them (see TypeMap::mapOver)
+ // TypeVars get applied to different arguments over time (in asSeenFrom)
+ // -- see pos/tcpoly_infer_implicit_tuplewrapper.scala
+ // thus: make new TypeVar's for every application of a TV to args,
+ // inference may generate several TypeVar's for a single type parameter that must be inferred,
+ // only one of them is in the set of tvars that need to be solved, but
+ // they share the same TypeConstraint instance
def setInst(tp: Type) {
@@ -2049,17 +2057,17 @@ A type's typeSymbol should never be inspected directly.
constr.inst = tp
}
- /** Can this variable be related in a constraint to type `tp'?
- * This is not the case if `tp' contains type skolems whose
- * skolemization level is higher than the level of this variable.
- */
- def isRelatable(tp: Type): Boolean =
- !tp.exists { t =>
- t.typeSymbol match {
- case ts: TypeSkolem => ts.level > level
- case _ => false
- }
- }
+ def addLoBound(tp: Type, numBound: Boolean = false) {
+ assert(tp != this) // implies there is a cycle somewhere (?)
+ //println("addLoBound: "+(safeToString, debugString(tp))) //DEBUG
+ constr.addLoBound(tp, numBound)
+ }
+
+ def addHiBound(tp: Type, numBound: Boolean = false) {
+ // assert(tp != this)
+ //println("addHiBound: "+(safeToString, debugString(tp))) //DEBUG
+ constr.addHiBound(tp, numBound)
+ }
/** Called from isSubtype0 when a TypeVar is involved in a subtyping check.
* if isLowerBound is true,
@@ -2084,8 +2092,8 @@ A type's typeSymbol should never be inspected directly.
else tp2 <:< tp1
def addBound(tp: Type) = {
- if (isLowerBound) constr.addLoBound(tp, numBound)
- else constr.addHiBound(tp, numBound)
+ if (isLowerBound) addLoBound(tp, numBound)
+ else addHiBound(tp, numBound)
// println("addedBound: "+(this, tp)) // @MDEBUG
}
@@ -2127,6 +2135,18 @@ A type's typeSymbol should never be inspected directly.
}
}
+ /** Can this variable be related in a constraint to type `tp'?
+ * This is not the case if `tp' contains type skolems whose
+ * skolemization level is higher than the level of this variable.
+ */
+ def isRelatable(tp: Type): Boolean =
+ !tp.exists { t =>
+ t.typeSymbol match {
+ case ts: TypeSkolem => ts.level > level
+ case _ => false
+ }
+ }
+
override val isHigherKinded = typeArgs.isEmpty && !params.isEmpty
override def normalize: Type =
@@ -4065,7 +4085,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
}
@@ -4282,14 +4302,13 @@ A type's typeSymbol should never be inspected directly.
val up = if (variance != CONTRAVARIANT) upper else !upper
tvar.constr.inst = null
val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo
- //Console.println("solveOne0 "+tvar+" "+config+" "+bound);//DEBUG
+ //Console.println("solveOne0(tv, tp, v, b)="+(tvar, tparam, variance, bound))
var cyclic = bound contains tparam
for ((tvar2, (tparam2, variance2)) <- config) {
- // Console.println("solveOne0(tp,up,lo,hi,lo=tp,hi=tp)="+(tparam.tpe, up, tparam2.info.bounds.lo, tparam2.info.bounds.hi, (tparam2.info.bounds.lo =:= tparam.tpe), (tparam2.info.bounds.hi =:= tparam.tpe))) //DEBUG
if (tparam2 != tparam &&
((bound contains tparam2) ||
- up && (tparam2.info.bounds.lo =:= tparam.tpe) || //@M TODO: should probably be .tpeHK
- !up && (tparam2.info.bounds.hi =:= tparam.tpe))) { //@M TODO: should probably be .tpeHK
+ up && (tparam2.info.bounds.lo =:= tparam.tpe) ||
+ !up && (tparam2.info.bounds.hi =:= tparam.tpe))) {
if (tvar2.constr.inst eq null) cyclic = true
solveOne(tvar2, tparam2, variance2)
}
@@ -4297,31 +4316,29 @@ A type's typeSymbol should never be inspected directly.
if (!cyclic) {
if (up) {
if (bound.typeSymbol != AnyClass)
- tvar.constr addHiBound bound.instantiateTypeParams(tparams, tvars)
+ tvar addHiBound bound.instantiateTypeParams(tparams, tvars)
for (tparam2 <- tparams)
- if (tparam2.info.bounds.lo =:= tparam.tpe) //@M TODO: should probably be .tpeHK
- tvar.constr addHiBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
+ if (tparam2.info.bounds.lo =:= tparam.tpe) // declaration tp2 :> tparam implies ?tparam <: tp2
+ tvar addHiBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
} else {
- if (bound.typeSymbol != NothingClass && bound.typeSymbol != tparam)
- tvar.constr addLoBound bound.instantiateTypeParams(tparams, tvars)
+ if (bound.typeSymbol != NothingClass && bound.typeSymbol != tparam) {
+ tvar addLoBound bound.instantiateTypeParams(tparams, tvars)
+ }
for (tparam2 <- tparams)
- if (tparam2.info.bounds.hi =:= tparam.tpe) //@M TODO: should probably be .tpeHK
- tvar.constr addLoBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
+ if (tparam2.info.bounds.hi =:= tparam.tpe)
+ tvar addLoBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
}
}
tvar.constr.inst = NoType // necessary because hibounds/lobounds may contain tvar
- // println("solveOne(useGlb, glb, lub): "+ (up, //@MDEBUG
- // if (depth != AnyDepth) glb(tvar.constr.hiBounds, depth) else glb(tvar.constr.hiBounds),
- // if (depth != AnyDepth) lub(tvar.constr.loBounds, depth) else lub(tvar.constr.loBounds)))
-
tvar setInst (
if (up) {
if (depth != AnyDepth) glb(tvar.constr.hiBounds, depth) else glb(tvar.constr.hiBounds)
} else {
if (depth != AnyDepth) lub(tvar.constr.loBounds, depth) else lub(tvar.constr.loBounds)
})
- // Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))+" = "+tvar.constr.inst)//@MDEBUG
+
+ //Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))+" = "+tvar.constr.inst)//@MDEBUG
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 8ed799ed60..0c3e34f8c5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -356,6 +356,8 @@ trait Infer {
context.unit.depends += sym.toplevelClass
val sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]))
+ // Console.println("check acc " + (sym, sym1) + ":" + (sym.tpe, sym1.tpe) + " from " + pre);//DEBUG
+
if (sym1 == NoSymbol) {
if (settings.debug.value) {
Console.println(context)
@@ -364,26 +366,9 @@ trait Infer {
}
accessError("")
} else {
- // Modify symbol's type so that raw types C
- // are converted to existentials C[T] forSome { type T }.
- // We can't do this on class loading because it would result
- // in infinite cycles.
- def cook(sym: Symbol) {
- val tpe1 = rawToExistential(sym.tpe)
- if (tpe1 ne sym.tpe) {
- if (settings.debug.value) println("cooked: "+sym+":"+sym.tpe)
- sym.setInfo(tpe1)
- }
- }
- if (sym1.isTerm) {
- if (sym1 hasFlag JAVA)
- cook(sym1)
- else if (sym1 hasFlag OVERLOADED)
- for (sym2 <- sym1.alternatives)
- if (sym2 hasFlag JAVA)
- cook(sym2)
- }
- //Console.println("check acc " + sym1 + ":" + sym1.tpe + " from " + pre);//DEBUG
+ if(sym1.isTerm)
+ sym1.cookJavaRawInfo() // xform java rawtypes into existentials
+
var owntype = try{
pre.memberType(sym1)
} catch {
@@ -884,7 +869,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 +1366,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 +1381,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 +1397,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 +1434,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)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index aaefab1f74..9b8be2aaec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -370,6 +370,8 @@ abstract class RefChecks extends InfoTransform {
kindErrors.toList.mkString("\n", ", ", ""))
}
} else if (other.isTerm) {
+ other.cookJavaRawInfo() // #2454
+
if (!overridesType(self.memberInfo(member), self.memberInfo(other))) { // 8
overrideTypeError()
explainTypes(self.memberInfo(member), self.memberInfo(other))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a7fd4f3a50..6e6fdd3c35 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1007,7 +1007,7 @@ trait Typers { self: Analyzer =>
// (if we allow this, we get divergence, e.g., starting at `conforms` during ant quick.bin)
// note: implicit arguments are still inferred (this kind of "chaining" is allowed)
if (qtpe.normalize.isInstanceOf[ExistentialType]) {
- qtpe = qtpe.normalize.skolemizeExistential(context.owner, qual)
+ qtpe = qtpe.normalize.skolemizeExistential(context.owner, qual) // open the existential
qual setType qtpe
}
val coercion = inferView(qual, qtpe, searchTemplate, true)