Skip to content

Commit 7030544

Browse files
committed
Fix a problem in IsFullyDefinedAccumulator
A maximized type variable could be instantiated to a type that contains more type variables. These have to be instantiated in turn.
1 parent 0c96231 commit 7030544

File tree

3 files changed

+34
-24
lines changed

3 files changed

+34
-24
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import reporting.diagnostic.Message
1717
import config.Printers.{gadts, typr}
1818
import typer.Applications._
1919
import typer.ProtoTypes._
20-
import typer.ForceDegree
20+
import typer.{ForceDegree, IfBottom}
2121
import typer.Inferencing.isFullyDefined
2222

2323
import scala.annotation.internal.sharable
@@ -644,7 +644,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
644644
tvar =>
645645
!(ctx.typerState.constraint.entry(tvar.origin) `eq` tvar.origin.underlying) ||
646646
(tvar `eq` removeThisType.prefixTVar),
647-
allowBottom = false
647+
IfBottom.maximize
648648
)
649649

650650
// If parent contains a reference to an abstract type, then we should

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

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ object Inferencing {
5555
def instantiateSelected(tp: Type, tvars: List[Type])(implicit ctx: Context): Unit =
5656
if (tvars.nonEmpty)
5757
IsFullyDefinedAccumulator(
58-
ForceDegree.Value(tvars.contains, allowBottom = false), minimizeSelected = true
58+
ForceDegree.Value(tvars.contains, IfBottom.maximize), minimizeSelected = true
5959
).process(tp)
6060

6161
/** Instantiate any type variables in `tp` whose bounds contain a reference to
@@ -132,7 +132,9 @@ object Inferencing {
132132
if tvar.hasLowerBound then instantiate(tvar, fromBelow = true)
133133
else if tvar.hasUpperBound then instantiate(tvar, fromBelow = false)
134134
else () // hold off instantiating unbounded unconstrained variables
135-
else if variance >= 0 && (force.allowBottom || tvar.hasLowerBound) then
135+
else if variance >= 0
136+
&& (force.ifBottom == IfBottom.ok || tvar.hasLowerBound)
137+
then
136138
instantiate(tvar, fromBelow = true)
137139
else
138140
toMaximize = tvar :: toMaximize
@@ -150,9 +152,14 @@ object Inferencing {
150152
if !tvar.isInstantiated then
151153
instantiate(tvar, fromBelow = false)
152154
case nil =>
153-
val res = apply(true, tp)
154-
if res then maximize(toMaximize)
155-
res
155+
apply(true, tp)
156+
&& (
157+
toMaximize.isEmpty
158+
|| { maximize(toMaximize)
159+
toMaximize = Nil // Do another round since the maximixing instances
160+
process(tp) // might have type uninstantiated variables themselves.
161+
}
162+
)
156163
}
157164

158165
/** For all type parameters occurring in `tp`:
@@ -508,10 +515,15 @@ trait Inferencing { this: Typer =>
508515
}
509516

510517
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
511-
@sharable object ForceDegree {
512-
class Value(val appliesTo: TypeVar => Boolean, val allowBottom: Boolean)
513-
val none: Value = new Value(_ => false, allowBottom = true)
514-
val all: Value = new Value(_ => true, allowBottom = true)
515-
val noBottom: Value = new Value(_ => true, allowBottom = false)
516-
}
518+
@sharable object ForceDegree:
519+
class Value(val appliesTo: TypeVar => Boolean, val ifBottom: IfBottom)
520+
val none: Value = new Value(_ => false, ifBottom = IfBottom.ok)
521+
val all: Value = new Value(_ => true, ifBottom = IfBottom.ok)
522+
val noBottom: Value = new Value(_ => true, ifBottom = IfBottom.maximize)
523+
524+
/** How to react when trying to instantiate a type variable without lower bound */
525+
enum IfBottom:
526+
case ok // instantiate to Nothing
527+
case maximize // maximize to upper bound
528+
case maximizeUpTo(tp: Type) // maximize to glb of upper bound and `tp`.
517529

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,20 +1044,18 @@ class Typer extends Namer
10441044
* type in MT, if this one is fully defined.
10451045
* If both attempts fail, issue a "missing parameter type" error.
10461046
*/
1047-
def inferredParamType(param: untpd.ValDef, formal: Type): Type = {
1048-
if (isFullyDefined(formal, ForceDegree.noBottom)) return formal
1049-
calleeType.widen match {
1047+
def inferredParamType(param: untpd.ValDef, formal: Type): Type =
1048+
if isFullyDefined(formal, ForceDegree.noBottom) then return formal
1049+
val target = calleeType.widen match
10501050
case mtpe: MethodType =>
10511051
val pos = paramIndex(param.name)
1052-
if (pos < mtpe.paramInfos.length) {
1052+
if pos < mtpe.paramInfos.length then
10531053
val ptype = mtpe.paramInfos(pos)
1054-
if (isFullyDefined(ptype, ForceDegree.noBottom) && !ptype.isRepeatedParam)
1055-
return ptype
1056-
}
1057-
case _ =>
1058-
}
1059-
errorType(AnonymousFunctionMissingParamType(param, params, tree, formal), param.sourcePos)
1060-
}
1054+
if ptype.isRepeatedParam then NoType else ptype
1055+
else NoType
1056+
case _ => NoType
1057+
if target.exists && isFullyDefined(target, ForceDegree.noBottom) then target
1058+
else errorType(AnonymousFunctionMissingParamType(param, params, tree, formal), param.sourcePos)
10611059

10621060
def protoFormal(i: Int): Type =
10631061
if (protoFormals.length == params.length) protoFormals(i)

0 commit comments

Comments
 (0)