@@ -5,7 +5,7 @@ package patmat
5
5
6
6
import core .* , Constants .* , Contexts .* , Decorators .* , Flags .* , Names .* , NameOps .* , StdNames .* , Symbols .* , Types .*
7
7
import ast .* , tpd .*
8
- import config .Printers .*
8
+ import config .Printers .exhaustivity
9
9
import printing .{ Printer , * }, Texts .*
10
10
import reporting .*
11
11
import typer .* , Applications .* , Inferencing .* , ProtoTypes .*
@@ -531,14 +531,48 @@ object SpaceEngine {
531
531
val mt : MethodType = unapp.widen match {
532
532
case mt : MethodType => mt
533
533
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
534
556
val tvars = constrained(pt)
535
557
val mt = pt.instantiate(tvars).asInstanceOf [MethodType ]
536
- scrutineeTp <:< mt.paramInfos(0 )
558
+ val unapplyArgType = mt.paramInfos.head
559
+ scrutineeTp <:< unapplyArgType
537
560
// force type inference to infer a narrower type: could be singleton
538
561
// 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 )
542
576
mt
543
577
}
544
578
0 commit comments