Skip to content

Commit b908232

Browse files
author
Adriaan Moors
committed
cleaned up inferConstructorInstance; same behavior
1 parent 9ca7297 commit b908232

File tree

1 file changed

+54
-37
lines changed

1 file changed

+54
-37
lines changed

src/compiler/scala/tools/nsc/typechecker/Infer.scala

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,49 +1051,66 @@ trait Infer {
10511051
* @param pt the expected result type of the instance
10521052
*/
10531053
def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type) {
1054-
val pt = widen(pt0)
1055-
//println("infer constr inst "+tree+"/"+undetparams+"/"+pt0)
1056-
var restpe = tree.tpe.finalResultType
1057-
var tvars = undetparams map freshVar
1054+
val pt = widen(pt0)
1055+
val ptparams = freeTypeParamsOfTerms.collect(pt)
1056+
val ctorTp = tree.tpe
1057+
val resTp = ctorTp.finalResultType
10581058

1059-
/** Compute type arguments for undetermined params and substitute them in given tree.
1059+
debuglog("infer constr inst "+ tree +"/"+ undetparams +"/ pt= "+ pt +" pt0= "+ pt0 +" resTp: "+ resTp)
1060+
1061+
/** Compute type arguments for undetermined params
10601062
*/
1061-
def computeArgs =
1062-
try {
1063-
val targs = solvedTypes(tvars, undetparams, undetparams map varianceInType(restpe),
1064-
true, lubDepth(List(restpe, pt)))
1065-
// checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
1066-
// no checkBounds here. If we enable it, test bug602 fails.
1067-
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
1068-
} catch ifNoInstance{ msg =>
1069-
NoConstructorInstanceError(tree, restpe, pt, msg)
1063+
def inferFor(pt: Type): Option[List[Type]] = {
1064+
val tvars = undetparams map freshVar
1065+
val resTpV = resTp.instantiateTypeParams(undetparams, tvars)
1066+
1067+
if (resTpV <:< pt) {
1068+
try {
1069+
// debuglog("TVARS "+ (tvars map (_.constr)))
1070+
// look at the argument types of the primary constructor corresponding to the pattern
1071+
val variances = undetparams map varianceInType(ctorTp)
1072+
val targs = solvedTypes(tvars, undetparams, variances, true, lubDepth(List(resTp, pt)))
1073+
// checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
1074+
// no checkBounds here. If we enable it, test bug602 fails.
1075+
// TODO: reinstate checkBounds, return params that fail to meet their bounds to undetparams
1076+
Some(targs)
1077+
} catch ifNoInstance { msg =>
1078+
debuglog("NO INST "+ (tvars, tvars map (_.constr)))
1079+
NoConstructorInstanceError(tree, resTp, pt, msg)
1080+
None
1081+
}
1082+
} else {
1083+
debuglog("not a subtype: "+ resTpV +" </:< "+ pt)
1084+
None
10701085
}
1071-
def instError = {
1072-
if (settings.debug.value) Console.println("ici " + tree + " " + undetparams + " " + pt)
1073-
if (settings.explaintypes.value) explainTypes(restpe.instantiateTypeParams(undetparams, tvars), pt)
1074-
ConstrInstantiationError(tree, restpe, pt)
10751086
}
1076-
if (restpe.instantiateTypeParams(undetparams, tvars) <:< pt) {
1077-
computeArgs
1078-
} else if (isFullyDefined(pt)) {
1079-
debuglog("infer constr " + tree + ":" + restpe + ", pt = " + pt)
1080-
var ptparams = freeTypeParamsOfTerms.collect(pt)
1081-
debuglog("free type params = " + ptparams)
1082-
val ptWithWildcards = pt.instantiateTypeParams(ptparams, ptparams map (ptparam => WildcardType))
1083-
tvars = undetparams map freshVar
1084-
if (restpe.instantiateTypeParams(undetparams, tvars) <:< ptWithWildcards) {
1085-
computeArgs
1086-
restpe = skipImplicit(tree.tpe.resultType)
1087-
debuglog("new tree = " + tree + ":" + restpe)
1088-
val ptvars = ptparams map freshVar
1089-
val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
1090-
if (isPopulated(restpe, pt1)) {
1091-
ptvars foreach instantiateTypeVar
1092-
} else { if (settings.debug.value) Console.println("no instance: "); instError }
1093-
} else { if (settings.debug.value) Console.println("not a subtype " + restpe.instantiateTypeParams(undetparams, tvars) + " of " + ptWithWildcards); instError }
1094-
} else { if (settings.debug.value) Console.println("not fully defined: " + pt); instError }
1087+
1088+
def inferForApproxPt =
1089+
if (isFullyDefined(pt)) {
1090+
inferFor(pt.instantiateTypeParams(ptparams, ptparams map (x => WildcardType))) flatMap { targs =>
1091+
val ctorTpInst = tree.tpe.instantiateTypeParams(undetparams, targs)
1092+
val resTpInst = skipImplicit(ctorTpInst.finalResultType)
1093+
val ptvars = ptparams map freshVar
1094+
val ptV = pt.instantiateTypeParams(ptparams, ptvars)
1095+
1096+
if (isPopulated(resTpInst, ptV)) {
1097+
ptvars foreach instantiateTypeVar
1098+
debuglog("isPopulated "+ resTpInst +", "+ ptV +" vars= "+ ptvars)
1099+
Some(targs)
1100+
} else None
1101+
}
1102+
} else None
1103+
1104+
(inferFor(pt) orElse inferForApproxPt) map { targs =>
1105+
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
1106+
} getOrElse {
1107+
debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)"))
1108+
// if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt)
1109+
ConstrInstantiationError(tree, resTp, pt)
1110+
}
10951111
}
10961112

1113+
10971114
def instBounds(tvar: TypeVar): (Type, Type) = {
10981115
val tparam = tvar.origin.typeSymbol
10991116
val instType = toOrigin(tvar.constr.inst)

0 commit comments

Comments
 (0)