@@ -5,7 +5,7 @@ package patmat
55
66import core .* , Constants .* , Contexts .* , Decorators .* , Flags .* , Names .* , NameOps .* , StdNames .* , Symbols .* , Types .*
77import ast .* , tpd .*
8- import config .Printers .*
8+ import config .Printers .exhaustivity
99import printing .{ Printer , * }, Texts .*
1010import reporting .*
1111import 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