diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index f4bbd74842c8..0acfd06de433 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -90,6 +90,7 @@ object Formatting { given Show[util.SourceFile] = ShowAny given Show[util.Spans.Span] = ShowAny given Show[tasty.TreeUnpickler#OwnerTree] = ShowAny + given Show[typer.ForceDegree.Value] = ShowAny private def show1[A: Show](x: A)(using Context) = show2(Show[A].show(x).ctxShow) private def show2(x: Shown)(using Context): String = x match diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index 656a1266d5ab..dc83b49a8aa3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -170,14 +170,18 @@ object Inferencing { private var toMaximize: List[TypeVar] = Nil - def apply(x: Boolean, tp: Type): Boolean = - try tp.dealias match + def apply(x: Boolean, tp: Type): Boolean = trace(i"isFullyDefined($tp, $force)", typr) { + try { + val tpd = tp.dealias + if tpd ne tp then apply(x, tpd) + else tp match case _: WildcardType | _: ProtoType => false case tvar: TypeVar if !tvar.isInstantiated => force.appliesTo(tvar) && ctx.typerState.constraint.contains(tvar) && { + var fail = false val direction = instDirection(tvar.origin) if minimizeSelected then if direction <= 0 && tvar.hasLowerBound then @@ -190,17 +194,16 @@ object Inferencing { else if variance >= 0 && (force.ifBottom == IfBottom.ok || tvar.hasLowerBound) then instantiate(tvar, fromBelow = true) else if variance >= 0 && force.ifBottom == IfBottom.fail then - return false + fail = true else toMaximize = tvar :: toMaximize - foldOver(x, tvar) - } - case tp => - reporting.trace(s"IFT $tp") { - foldOver(x, tp) + !fail && foldOver(x, tvar) } + case tp => foldOver(x, tp) + } catch case ex: Throwable => handleRecursive("check fully defined", tp.show, ex) + } def process(tp: Type): Boolean = // Maximize type vars in the order they were visited before */ @@ -767,13 +770,14 @@ trait Inferencing { this: Typer => end constrainIfDependentParamRef } -/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */ +/** An enumeration controlling the degree of forcing in "is-fully-defined" checks. */ @sharable object ForceDegree { - class Value(val appliesTo: TypeVar => Boolean, val ifBottom: IfBottom) - val none: Value = new Value(_ => false, IfBottom.ok) - val all: Value = new Value(_ => true, IfBottom.ok) - val failBottom: Value = new Value(_ => true, IfBottom.fail) - val flipBottom: Value = new Value(_ => true, IfBottom.flip) + class Value(val appliesTo: TypeVar => Boolean, val ifBottom: IfBottom): + override def toString = s"ForceDegree.Value(.., $ifBottom)" + val none: Value = new Value(_ => false, IfBottom.ok) { override def toString = "ForceDegree.none" } + val all: Value = new Value(_ => true, IfBottom.ok) { override def toString = "ForceDegree.all" } + val failBottom: Value = new Value(_ => true, IfBottom.fail) { override def toString = "ForceDegree.failBottom" } + val flipBottom: Value = new Value(_ => true, IfBottom.flip) { override def toString = "ForceDegree.flipBottom" } } enum IfBottom: