@@ -584,10 +584,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
584584 // precondition: `tp1` should have the shape `path.Child`, thus `ThisType` is always covariant
585585 val thisTypeMap = new TypeMap {
586586 def apply (t : Type ): Type = t match {
587- case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner && ! tref.symbol.is(Module ) =>
588- // TODO: stackoverflow here
589- // newTypeVar(TypeBounds.upper(mapOver(tp.underlying)))
590- newTypeVar(TypeBounds .upper(mapOver(tref & tref.classSymbol.asClass.givenSelfType)))
587+ case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
588+ if (tref.symbol.is(Module )) mapOver(tref)
589+ else newTypeVar(TypeBounds .upper(tp.underlying))
591590 case _ =>
592591 mapOver(t)
593592 }
@@ -596,7 +595,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
596595 // replace type parameter references with bounds
597596 val typeParamMap = new TypeMap {
598597 def apply (t : Type ): Type = t match {
599-
600598 case tp : TypeRef if tp.symbol.is(TypeParam ) && tp.underlying.isInstanceOf [TypeBounds ] =>
601599 // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
602600 val exposed =
@@ -611,13 +609,32 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
611609 }
612610 }
613611
612+ // replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
613+ val instUndetMap = new TypeMap {
614+ def apply (t : Type ): Type = t match {
615+ case tvar : TypeVar if ! tvar.isInstantiated => WildcardType (tvar.origin.underlying.bounds)
616+ case _ => mapOver(t)
617+ }
618+ }
619+
620+ val force = new ForceDegree .Value (
621+ tvar => ! (ctx.typerState.constraint.entry(tvar.origin) eq tvar.origin.underlying),
622+ minimizeAll = false
623+ )
624+
614625 val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
615626 val protoTp1 = thisTypeMap(tp1.appliedTo(tvars))
616627
617- if (protoTp1 <:< tp2 && isFullyDefined(protoTp1, ForceDegree .noBottom)) protoTp1
628+ if (protoTp1 <:< tp2) {
629+ if (isFullyDefined(protoTp1, force)) protoTp1
630+ else instUndetMap(protoTp1)
631+ }
618632 else {
619633 val protoTp2 = typeParamMap(tp2)
620- if (protoTp1 <:< protoTp2 && isFullyDefined(protoTp1 & protoTp2, ForceDegree .noBottom)) protoTp1
634+ if (protoTp1 <:< protoTp2) {
635+ if (isFullyDefined(AndType (protoTp1, protoTp2), force)) protoTp1
636+ else instUndetMap(protoTp1)
637+ }
621638 else {
622639 debug.println(s " $protoTp1 <:< $protoTp2 = false " )
623640 NoType
0 commit comments