Skip to content

Commit 6be6e3a

Browse files
dwijnandtgodzik
authored andcommitted
Optimise SpaceEngine.signature for synthetic unapplies
Instead of creating type vars, constraining against them, then instantiating them, just instantiate the PolyType with the scrutinee type args (or the lo/hi bound or bounded wildcard from the param).
1 parent fca51d3 commit 6be6e3a

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4636,6 +4636,7 @@ object Types extends TypeUtils {
46364636
type BT <: LambdaType
46374637
def paramNum: Int
46384638
def paramName: binder.ThisName = binder.paramNames(paramNum)
4639+
def paramInfo: binder.PInfo = binder.paramInfos(paramNum)
46394640

46404641
override def underlying(using Context): Type = {
46414642
// TODO: update paramInfos's type to nullable

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package patmat
55

66
import core.*, Constants.*, Contexts.*, Decorators.*, Flags.*, Names.*, NameOps.*, StdNames.*, Symbols.*, Types.*
77
import ast.*, tpd.*
8-
import config.Printers.*
8+
import config.Printers.exhaustivity
99
import printing.{ Printer, * }, Texts.*
1010
import reporting.*
1111
import typer.*, Applications.*, Inferencing.*, ProtoTypes.*
@@ -531,14 +531,48 @@ object SpaceEngine {
531531
val mt: MethodType = unapp.widen match {
532532
case mt: MethodType => mt
533533
case pt: PolyType =>
534+
if unappSym.is(Synthetic) then
535+
val mt = pt.resultType.asInstanceOf[MethodType]
536+
val unapplyArgType = mt.paramInfos.head
537+
val targs = scrutineeTp.baseType(unapplyArgType.classSymbol) match
538+
case AppliedType(_, targs) => targs
539+
case _ =>
540+
// Typically when the scrutinee is Null or Nothing (see i5067 and i5067b)
541+
// For performance, do `variances(unapplyArgType)` but without using TypeVars
542+
// so just find the variance, so we know if to min/max to the LB/UB or use a wildcard.
543+
object accu extends TypeAccumulator[VarianceMap[TypeParamRef]]:
544+
def apply(vmap: VarianceMap[TypeParamRef], tp: Type) = tp match
545+
case tp: TypeParamRef if tp.binder eq pt => vmap.recordLocalVariance(tp, variance)
546+
case _ => foldOver(vmap, tp)
547+
val vs = accu(VarianceMap.empty[TypeParamRef], unapplyArgType)
548+
pt.paramRefs.map: p =>
549+
vs.computedVariance(p).uncheckedNN match
550+
case -1 => p.paramInfo.lo
551+
case 1 => p.paramInfo.hi
552+
case _ => WildcardType(p.paramInfo)
553+
pt.instantiate(targs).asInstanceOf[MethodType]
554+
else
555+
val locked = ctx.typerState.ownedVars
534556
val tvars = constrained(pt)
535557
val mt = pt.instantiate(tvars).asInstanceOf[MethodType]
536-
scrutineeTp <:< mt.paramInfos(0)
558+
val unapplyArgType = mt.paramInfos.head
559+
scrutineeTp <:< unapplyArgType
537560
// force type inference to infer a narrower type: could be singleton
538561
// see tests/patmat/i4227.scala
539-
mt.paramInfos(0) <:< scrutineeTp
540-
instantiateSelected(mt, tvars)
541-
isFullyDefined(mt, ForceDegree.all)
562+
unapplyArgType <:< scrutineeTp
563+
maximizeType(unapplyArgType, Spans.NoSpan)
564+
if !(ctx.typerState.ownedVars -- locked).isEmpty then
565+
// constraining can create type vars out of wildcard types
566+
// (in legalBound, by using a LevelAvoidMap)
567+
// maximise will only do one pass at maximising the type vars in the target type
568+
// which means we can maximise to types that include other type vars
569+
// this fails TreeChecker's "non-empty constraint at end of $fusedPhase" check
570+
// e.g. run-macros/string-context-implicits
571+
// I can't prove that a second call won't also create type vars,
572+
// but I'd rather have an unassigned new-new type var, than an infinite loop.
573+
// After all, there's nothing strictly "wrong" with unassigned type vars,
574+
// it just fails TreeChecker's linting.
575+
maximizeType(unapplyArgType, Spans.NoSpan)
542576
mt
543577
}
544578

0 commit comments

Comments
 (0)