summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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)