summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-03-02 17:33:34 +0100
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-03-09 08:59:13 +0100
commitb9082321219f78a86e80fcea2a71d96ee4beb397 (patch)
treef17c0b1dfb190cb23dfc5c01a17ece705c865198 /src
parent9ca7297588538c5f1ee6cd8e535be41dac9031a6 (diff)
downloadscala-b9082321219f78a86e80fcea2a71d96ee4beb397.tar.gz
scala-b9082321219f78a86e80fcea2a71d96ee4beb397.tar.bz2
scala-b9082321219f78a86e80fcea2a71d96ee4beb397.zip
cleaned up inferConstructorInstance; same behavior
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala91
1 files changed, 54 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index c09e535117..310198ec0c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1051,49 +1051,66 @@ trait Infer {
* @param pt the expected result type of the instance
*/
def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type) {
- val pt = widen(pt0)
- //println("infer constr inst "+tree+"/"+undetparams+"/"+pt0)
- var restpe = tree.tpe.finalResultType
- var tvars = undetparams map freshVar
+ val pt = widen(pt0)
+ val ptparams = freeTypeParamsOfTerms.collect(pt)
+ val ctorTp = tree.tpe
+ val resTp = ctorTp.finalResultType
- /** Compute type arguments for undetermined params and substitute them in given tree.
+ debuglog("infer constr inst "+ tree +"/"+ undetparams +"/ pt= "+ pt +" pt0= "+ pt0 +" resTp: "+ resTp)
+
+ /** Compute type arguments for undetermined params
*/
- def computeArgs =
- try {
- val targs = solvedTypes(tvars, undetparams, undetparams map varianceInType(restpe),
- true, lubDepth(List(restpe, pt)))
-// checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
-// no checkBounds here. If we enable it, test bug602 fails.
- new TreeTypeSubstituter(undetparams, targs).traverse(tree)
- } catch ifNoInstance{ msg =>
- NoConstructorInstanceError(tree, restpe, pt, msg)
+ def inferFor(pt: Type): Option[List[Type]] = {
+ val tvars = undetparams map freshVar
+ val resTpV = resTp.instantiateTypeParams(undetparams, tvars)
+
+ if (resTpV <:< pt) {
+ try {
+ // debuglog("TVARS "+ (tvars map (_.constr)))
+ // look at the argument types of the primary constructor corresponding to the pattern
+ val variances = undetparams map varianceInType(ctorTp)
+ val targs = solvedTypes(tvars, undetparams, variances, true, lubDepth(List(resTp, pt)))
+ // checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
+ // no checkBounds here. If we enable it, test bug602 fails.
+ // TODO: reinstate checkBounds, return params that fail to meet their bounds to undetparams
+ Some(targs)
+ } catch ifNoInstance { msg =>
+ debuglog("NO INST "+ (tvars, tvars map (_.constr)))
+ NoConstructorInstanceError(tree, resTp, pt, msg)
+ None
+ }
+ } else {
+ debuglog("not a subtype: "+ resTpV +" </:< "+ pt)
+ None
}
- def instError = {
- if (settings.debug.value) Console.println("ici " + tree + " " + undetparams + " " + pt)
- if (settings.explaintypes.value) explainTypes(restpe.instantiateTypeParams(undetparams, tvars), pt)
- ConstrInstantiationError(tree, restpe, pt)
}
- if (restpe.instantiateTypeParams(undetparams, tvars) <:< pt) {
- computeArgs
- } else if (isFullyDefined(pt)) {
- debuglog("infer constr " + tree + ":" + restpe + ", pt = " + pt)
- var ptparams = freeTypeParamsOfTerms.collect(pt)
- debuglog("free type params = " + ptparams)
- val ptWithWildcards = pt.instantiateTypeParams(ptparams, ptparams map (ptparam => WildcardType))
- tvars = undetparams map freshVar
- if (restpe.instantiateTypeParams(undetparams, tvars) <:< ptWithWildcards) {
- computeArgs
- restpe = skipImplicit(tree.tpe.resultType)
- debuglog("new tree = " + tree + ":" + restpe)
- val ptvars = ptparams map freshVar
- val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
- if (isPopulated(restpe, pt1)) {
- ptvars foreach instantiateTypeVar
- } else { if (settings.debug.value) Console.println("no instance: "); instError }
- } else { if (settings.debug.value) Console.println("not a subtype " + restpe.instantiateTypeParams(undetparams, tvars) + " of " + ptWithWildcards); instError }
- } else { if (settings.debug.value) Console.println("not fully defined: " + pt); instError }
+
+ def inferForApproxPt =
+ if (isFullyDefined(pt)) {
+ inferFor(pt.instantiateTypeParams(ptparams, ptparams map (x => WildcardType))) flatMap { targs =>
+ val ctorTpInst = tree.tpe.instantiateTypeParams(undetparams, targs)
+ val resTpInst = skipImplicit(ctorTpInst.finalResultType)
+ val ptvars = ptparams map freshVar
+ val ptV = pt.instantiateTypeParams(ptparams, ptvars)
+
+ if (isPopulated(resTpInst, ptV)) {
+ ptvars foreach instantiateTypeVar
+ debuglog("isPopulated "+ resTpInst +", "+ ptV +" vars= "+ ptvars)
+ Some(targs)
+ } else None
+ }
+ } else None
+
+ (inferFor(pt) orElse inferForApproxPt) map { targs =>
+ new TreeTypeSubstituter(undetparams, targs).traverse(tree)
+ } getOrElse {
+ debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)"))
+ // if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt)
+ ConstrInstantiationError(tree, resTp, pt)
+ }
}
+
def instBounds(tvar: TypeVar): (Type, Type) = {
val tparam = tvar.origin.typeSymbol
val instType = toOrigin(tvar.constr.inst)