Skip to content

Commit e013788

Browse files
committed
Fix problem with partly uninstantiated dependent functions
If the result type of a dependent function contains a type variable whose bounds refer to the function's parameters, that type variable has to be instantiated before the method type is formed. Otherwise, if the type variable is instantiated later the method result type will refer to the original parameter symbols instead of the method types ParamRefs.
1 parent 382e4ce commit e013788

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,27 @@ object Inferencing {
4949
def instantiateSelected(tp: Type, tvars: List[Type])(implicit ctx: Context): Unit =
5050
new IsFullyDefinedAccumulator(new ForceDegree.Value(tvars.contains, minimizeAll = true)).process(tp)
5151

52+
/** Instantiate any type variables in `tp` whose bounds contain a reference to
53+
* one of the parameters in `tparams` or `vparamss`.
54+
*/
55+
def instantiateDependent(tp: Type, tparams: List[Symbol], vparamss: List[List[Symbol]])(implicit ctx: Context): Unit = {
56+
val dependentVars = new TypeAccumulator[Set[TypeVar]] {
57+
lazy val params = (vparamss :\ tparams)( _ ::: _)
58+
def apply(tvars: Set[TypeVar], tp: Type) = tp match {
59+
case tp: TypeVar
60+
if !tp.isInstantiated &&
61+
ctx.typeComparer.bounds(tp.origin)
62+
.namedPartsWith(ref => params.contains(ref.symbol))
63+
.nonEmpty =>
64+
tvars + tp
65+
case _ =>
66+
foldOver(tvars, tp)
67+
}
68+
}
69+
val depVars = dependentVars(Set(), tp)
70+
if (depVars.nonEmpty) instantiateSelected(tp, depVars.toList)
71+
}
72+
5273
/** The accumulator which forces type variables using the policy encoded in `force`
5374
* and returns whether the type is fully defined. The direction in which
5475
* a type variable is instantiated is determined as follows:

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@ trait NamerContextOps { this: Context =>
9696
else given
9797

9898
/** if isConstructor, make sure it has one non-implicit parameter list */
99-
def normalizeIfConstructor(paramSymss: List[List[Symbol]], isConstructor: Boolean) =
99+
def normalizeIfConstructor(termParamss: List[List[Symbol]], isConstructor: Boolean) =
100100
if (isConstructor &&
101-
(paramSymss.isEmpty || paramSymss.head.nonEmpty && (paramSymss.head.head is Implicit)))
102-
Nil :: paramSymss
101+
(termParamss.isEmpty || termParamss.head.nonEmpty && (termParamss.head.head is Implicit)))
102+
Nil :: termParamss
103103
else
104-
paramSymss
104+
termParamss
105105

106106
/** The method type corresponding to given parameters and result type */
107107
def methodType(typeParams: List[Symbol], valueParamss: List[List[Symbol]], resultType: Type, isJava: Boolean = false)(implicit ctx: Context): Type = {
@@ -1149,15 +1149,17 @@ class Namer { typer: Typer =>
11491149

11501150
vparamss foreach completeParams
11511151
def typeParams = tparams map symbolOfTree
1152-
val paramSymss = ctx.normalizeIfConstructor(vparamss.nestedMap(symbolOfTree), isConstructor)
1153-
def wrapMethType(restpe: Type): Type =
1154-
ctx.methodType(tparams map symbolOfTree, paramSymss, restpe, isJava = ddef.mods is JavaDefined)
1152+
val termParamss = ctx.normalizeIfConstructor(vparamss.nestedMap(symbolOfTree), isConstructor)
1153+
def wrapMethType(restpe: Type): Type = {
1154+
instantiateDependent(restpe, typeParams, termParamss)
1155+
ctx.methodType(tparams map symbolOfTree, termParamss, restpe, isJava = ddef.mods is JavaDefined)
1156+
}
11551157
if (isConstructor) {
11561158
// set result type tree to unit, but take the current class as result type of the symbol
11571159
typedAheadType(ddef.tpt, defn.UnitType)
11581160
wrapMethType(ctx.effectiveResultType(sym, typeParams, NoType))
11591161
}
1160-
else valOrDefDefSig(ddef, sym, typeParams, paramSymss, wrapMethType)
1162+
else valOrDefDefSig(ddef, sym, typeParams, termParamss, wrapMethType)
11611163
}
11621164

11631165
def typeDefSig(tdef: TypeDef, sym: Symbol, tparamSyms: List[TypeSymbol])(implicit ctx: Context): Type = {

0 commit comments

Comments
 (0)