summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/internal/Types.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-06-20 15:28:15 +0000
committerPaul Phillips <paulp@improving.org>2011-06-20 15:28:15 +0000
commitf0125bc5912ebe87a01c7e63094dc97757d2dee8 (patch)
treedf088a77722a5d99328ee07d73a8456988d6ecca /src/compiler/scala/reflect/internal/Types.scala
parent2627ab313f0d9f33e1b97e8aeda4447cf34bd27d (diff)
downloadscala-f0125bc5912ebe87a01c7e63094dc97757d2dee8.tar.gz
scala-f0125bc5912ebe87a01c7e63094dc97757d2dee8.tar.bz2
scala-f0125bc5912ebe87a01c7e63094dc97757d2dee8.zip
When TypeVars were given higher-order abilities...
When TypeVars were given higher-order abilities, so too should have been WildcardType, which acts as a plceholder for typevars. Always inflicting arguments upon it was the cause of #2308. Closes #2308, review by moors.
Diffstat (limited to 'src/compiler/scala/reflect/internal/Types.scala')
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala101
1 files changed, 68 insertions, 33 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 408c287d24..a6c26d037b 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -5595,10 +5595,11 @@ A type's typeSymbol should never be inspected directly.
}
-// TODO: this desperately needs to be cleaned up
-// plan: split into kind inference and subkinding
-// every Type has a (cached) Kind
- def kindsConform(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): Boolean = checkKindBounds0(tparams, targs, pre, owner, false).isEmpty
+ // TODO: this desperately needs to be cleaned up
+ // plan: split into kind inference and subkinding
+ // every Type has a (cached) Kind
+ def kindsConform(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): Boolean =
+ checkKindBounds0(tparams, targs, pre, owner, false).isEmpty
/** Check well-kindedness of type application (assumes arities are already checked) -- @M
*
@@ -5628,7 +5629,15 @@ A type's typeSymbol should never be inspected directly.
def variancesMatch(sym1: Symbol, sym2: Symbol): Boolean = (sym2.variance==0 || sym1.variance==sym2.variance)
// check that the type parameters <arg>hkargs</arg> to a higher-kinded type conform to the expected params <arg>hkparams</arg>
- def checkKindBoundsHK(hkargs: List[Symbol], arg: Symbol, param: Symbol, paramowner: Symbol, underHKParams: List[Symbol], withHKArgs: List[Symbol]): (List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = {
+ def checkKindBoundsHK(
+ hkargs: List[Symbol],
+ arg: Symbol,
+ param: Symbol,
+ paramowner: Symbol,
+ underHKParams: List[Symbol],
+ withHKArgs: List[Symbol]
+ ): (List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = {
+
def bindHKParams(tp: Type) = tp.substSym(underHKParams, withHKArgs)
// @M sometimes hkargs != arg.typeParams, the symbol and the type may have very different type parameters
val hkparams = param.typeParams
@@ -5640,12 +5649,14 @@ A type's typeSymbol should never be inspected directly.
}
if (!sameLength(hkargs, hkparams)) {
- if(arg == AnyClass || arg == NothingClass) (Nil, Nil, Nil) // Any and Nothing are kind-overloaded
- else {error = true; (List((arg, param)), Nil, Nil)} // shortcut: always set error, whether explainTypesOrNot
- } else {
- val _arityMismatches = if(explainErrors) new ListBuffer[(Symbol, Symbol)] else null
- val _varianceMismatches = if(explainErrors) new ListBuffer[(Symbol, Symbol)] else null
- val _stricterBounds = if(explainErrors)new ListBuffer[(Symbol, Symbol)] else null
+ if (arg == AnyClass || arg == NothingClass) (Nil, Nil, Nil) // Any and Nothing are kind-overloaded
+ else {error = true; (List((arg, param)), Nil, Nil) } // shortcut: always set error, whether explainTypesOrNot
+ }
+ else {
+ val _arityMismatches = if (explainErrors) new ListBuffer[(Symbol, Symbol)] else null
+ val _varianceMismatches = if (explainErrors) new ListBuffer[(Symbol, Symbol)] else null
+ val _stricterBounds = if (explainErrors) new ListBuffer[(Symbol, Symbol)] else null
+
def varianceMismatch(a: Symbol, p: Symbol) { if(explainErrors) _varianceMismatches += ((a, p)) else error = true}
def stricterBound(a: Symbol, p: Symbol) { if(explainErrors) _stricterBounds += ((a, p)) else error = true }
def arityMismatches(as: Iterable[(Symbol, Symbol)]) { if(explainErrors) _arityMismatches ++= as }
@@ -5661,42 +5672,66 @@ A type's typeSymbol should never be inspected directly.
// substSym(hkparams, hkargs) --> these types are going to be compared as types of kind *
// --> their arguments use different symbols, but are conceptually the same
// (could also replace the types by polytypes, but can't just strip the symbols, as ordering is lost then)
- if (!(bindHKParams(transformedBounds(hkparam, paramowner)) <:< transform(hkarg.info.bounds, owner)))
+ val declaredBounds = transformedBounds(hkparam, paramowner)
+ val declaredBoundsInst = bindHKParams(declaredBounds)
+ val argumentBounds = transform(hkarg.info.bounds, owner)
+ if (!(declaredBoundsInst <:< argumentBounds))
stricterBound(hkarg, hkparam)
- if (settings.debug.value) {
- log("checkKindBoundsHK base case: "+ hkparam +" declared bounds: "+ transformedBounds(hkparam, paramowner) +" after instantiating earlier hkparams: "+ bindHKParams(transformedBounds(hkparam, paramowner)))
- log("checkKindBoundsHK base case: "+ hkarg +" has bounds: "+ transform(hkarg.info.bounds, owner))
- }
- } else {
- if(settings.debug.value) log("checkKindBoundsHK recursing to compare params of "+ hkparam +" with "+ hkarg)
- val (am, vm, sb) = checkKindBoundsHK(hkarg.typeParams, hkarg, hkparam, paramowner, underHKParams ++ hkparam.typeParams, withHKArgs ++ hkarg.typeParams)
+ if (settings.debug.value) log(
+ "checkKindBoundsHK base case: " + hkparam +
+ " declared bounds: " + declaredBounds +
+ " after instantiating earlier hkparams: " + declaredBoundsInst + "\n" +
+ "checkKindBoundsHK base case: "+ hkarg +
+ " has bounds: " + argumentBounds
+ )
+ }
+ else {
+ if (settings.debug.value)
+ log("checkKindBoundsHK recursing to compare params of "+ hkparam +" with "+ hkarg)
+ val (am, vm, sb) = checkKindBoundsHK(
+ hkarg.typeParams,
+ hkarg,
+ hkparam,
+ paramowner,
+ underHKParams ++ hkparam.typeParams,
+ withHKArgs ++ hkarg.typeParams
+ )
arityMismatches(am)
varianceMismatches(vm)
stricterBounds(sb)
}
- if(!explainErrors && error) return (Nil, Nil, Nil) // stop as soon as we encountered an error
+ if (!explainErrors && error) return (Nil, Nil, Nil) // stop as soon as we encountered an error
}
- if(!explainErrors) (Nil, Nil, Nil)
+ if (!explainErrors) (Nil, Nil, Nil)
else (_arityMismatches.toList, _varianceMismatches.toList, _stricterBounds.toList)
}
}
val errors = new ListBuffer[(Type, Symbol, List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)])]
- (tparams zip targs).foreach{ case (tparam, targ) if (targ.isHigherKinded || !tparam.typeParams.isEmpty) =>
- // @M must use the typeParams of the type targ, not the typeParams of the symbol of targ!!
+ if (tparams.nonEmpty || targs.nonEmpty)
+ log("checkKindBounds0(" + tparams + ", " + targs + ", " + pre + ", " + owner + ", " + explainErrors + ")")
+
+ for {
+ (tparam, targ) <- tparams zip targs
+ // Prevent WildcardType from causing kind errors, as typevars may be higher-order
+ if (targ != WildcardType) && (targ.isHigherKinded || tparam.typeParams.nonEmpty)
+ } {
+ // @M must use the typeParams of the *type* targ, not of the *symbol* of targ!!
targ.typeSymbolDirect.info // force symbol load for #4205
- val tparamsHO = targ.typeParams
-
- val (arityMismatches, varianceMismatches, stricterBounds) =
- checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO) // NOTE: *not* targ.typeSymbol, which normalizes
-
- if(!explainErrors) {if(error) return List((NoType, NoSymbol, Nil, Nil, Nil))}
- else if (arityMismatches.nonEmpty || varianceMismatches.nonEmpty || stricterBounds.nonEmpty) {
- errors += ((targ, tparam, arityMismatches, varianceMismatches, stricterBounds))
+ val tparamsHO = targ.typeParams
+
+ val (arityMismatches, varianceMismatches, stricterBounds) = (
+ // NOTE: *not* targ.typeSymbol, which normalizes
+ checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
+ )
+ if (explainErrors) {
+ if (arityMismatches.nonEmpty || varianceMismatches.nonEmpty || stricterBounds.nonEmpty) {
+ errors += ((targ, tparam, arityMismatches, varianceMismatches, stricterBounds))
+ }
}
- // case (tparam, targ) => println("no check: "+(tparam, targ, tparam.typeParams.isEmpty))
- case _ =>
+ else if (error)
+ return List((NoType, NoSymbol, Nil, Nil, Nil))
}
errors.toList