@@ -466,10 +466,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
466
466
children.map(sym => Typ (sym.termRef, true ))
467
467
case tp =>
468
468
val parts = children.map { sym =>
469
- if (sym.is(ModuleClass ))
470
- refine(tp, sym.sourceModule)
471
- else
472
- refine(tp, sym)
469
+ val sym1 = if (sym.is(ModuleClass )) sym.sourceModule else sym
470
+ ctx.typer.refineUsingParent(tp, sym1)
473
471
} filter(_.exists)
474
472
475
473
debug.println(s " ${tp.show} decomposes to [ ${parts.map(_.show).mkString(" , " )}] " )
@@ -478,156 +476,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
478
476
}
479
477
}
480
478
481
- /** Refine child based on parent
482
- *
483
- * In child class definition, we have:
484
- *
485
- * class Child[Ts] extends path.Parent[Us] with Es
486
- * object Child extends path.Parent[Us] with Es
487
- * val child = new path.Parent[Us] with Es // enum values
488
- *
489
- * Given a parent type `parent` and a child symbol `child`, we infer the prefix
490
- * and type parameters for the child:
491
- *
492
- * prefix.child[Vs] <:< parent
493
- *
494
- * where `Vs` are fresh type variables and `prefix` is the symbol prefix with all
495
- * non-module and non-package `ThisType` replaced by fresh type variables.
496
- *
497
- * If the subtyping is true, the instantiated type `p.child[Vs]` is
498
- * returned. Otherwise, `NoType` is returned.
499
- *
500
- */
501
- def refine (parent : Type , child : Symbol ): Type = {
502
- if (child.isTerm && child.is(Case , butNot = Module )) return child.termRef // enum vals always match
503
-
504
- // <local child> is a place holder from Scalac, it is hopeless to instantiate it.
505
- //
506
- // Quote from scalac (from nsc/symtab/classfile/Pickler.scala):
507
- //
508
- // ...When a sealed class/trait has local subclasses, a single
509
- // <local child> class symbol is added as pickled child
510
- // (instead of a reference to the anonymous class; that was done
511
- // initially, but seems not to work, ...).
512
- //
513
- if (child.name == tpnme.LOCAL_CHILD ) return child.typeRef
514
-
515
- val childTp = if (child.isTerm) child.termRef else child.typeRef
516
-
517
- instantiate(childTp, parent)(ctx.fresh.setNewTyperState()).dealias
518
- }
519
-
520
- /** expose abstract type references to their bounds or tvars according to variance */
521
- private class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
522
- def expose (lo : Type , hi : Type ): Type =
523
- if (variance == 0 )
524
- newTypeVar(TypeBounds (lo, hi))
525
- else if (variance == 1 )
526
- if (maximize) hi else lo
527
- else
528
- if (maximize) lo else hi
529
-
530
- def apply (tp : Type ): Type = tp match {
531
- case tp : TypeRef if isBounds(tp.underlying) =>
532
- val lo = this (tp.info.loBound)
533
- val hi = this (tp.info.hiBound)
534
- // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
535
- val exposed = expose(lo, hi)
536
- debug.println(s " $tp exposed to =====> $exposed" )
537
- exposed
538
-
539
- case AppliedType (tycon : TypeRef , args) if isBounds(tycon.underlying) =>
540
- val args2 = args.map(this )
541
- val lo = this (tycon.info.loBound).applyIfParameterized(args2)
542
- val hi = this (tycon.info.hiBound).applyIfParameterized(args2)
543
- val exposed = expose(lo, hi)
544
- debug.println(s " $tp exposed to =====> $exposed" )
545
- exposed
546
-
547
- case _ =>
548
- mapOver(tp)
549
- }
550
- }
551
-
552
- private def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
553
- private def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
554
-
555
- /** Instantiate type `tp1` to be a subtype of `tp2`
556
- *
557
- * Return the instantiated type if type parameters and this type
558
- * in `tp1` can be instantiated such that `tp1 <:< tp2`.
559
- *
560
- * Otherwise, return NoType.
561
- *
562
- */
563
- def instantiate (tp1 : NamedType , tp2 : Type )(implicit ctx : Context ): Type = {
564
- // Fix subtype checking for child instantiation,
565
- // such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
566
- // See tests/patmat/i3938.scala
567
- class RemoveThisMap extends TypeMap {
568
- var prefixTVar : Type = null
569
- def apply (tp : Type ): Type = tp match {
570
- case ThisType (tref : TypeRef ) if ! tref.symbol.isStaticOwner =>
571
- if (tref.symbol.is(Module ))
572
- TermRef (this (tref.prefix), tref.symbol.sourceModule)
573
- else if (prefixTVar != null )
574
- this (tref)
575
- else {
576
- prefixTVar = WildcardType // prevent recursive call from assigning it
577
- prefixTVar = newTypeVar(TypeBounds .upper(this (tref)))
578
- prefixTVar
579
- }
580
- case tp => mapOver(tp)
581
- }
582
- }
583
-
584
- // replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
585
- def instUndetMap (implicit ctx : Context ) = new TypeMap {
586
- def apply (t : Type ): Type = t match {
587
- case tvar : TypeVar if ! tvar.isInstantiated => WildcardType (tvar.origin.underlying.bounds)
588
- case _ => mapOver(t)
589
- }
590
- }
591
-
592
- val removeThisType = new RemoveThisMap
593
- val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
594
- val protoTp1 = removeThisType.apply(tp1).appliedTo(tvars)
595
-
596
- val force = new ForceDegree .Value (
597
- tvar =>
598
- ! (ctx.typerState.constraint.entry(tvar.origin) `eq` tvar.origin.underlying) ||
599
- (tvar `eq` removeThisType.prefixTVar),
600
- minimizeAll = false ,
601
- allowBottom = false
602
- )
603
-
604
- // If parent contains a reference to an abstract type, then we should
605
- // refine subtype checking to eliminate abstract types according to
606
- // variance. As this logic is only needed in exhaustivity check,
607
- // we manually patch subtyping check instead of changing TypeComparer.
608
- // See tests/patmat/i3645b.scala
609
- def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
610
- implicit val ictx = ctx.fresh.setNewTyperState()
611
- parent.argInfos.nonEmpty && minTypeMap.apply(parent) <:< maxTypeMap.apply(tp2)
612
- }
613
-
614
- if (protoTp1 <:< tp2) {
615
- if (isFullyDefined(protoTp1, force)) protoTp1
616
- else instUndetMap.apply(protoTp1)
617
- }
618
- else {
619
- val protoTp2 = maxTypeMap.apply(tp2)
620
- if (protoTp1 <:< protoTp2 || parentQualify) {
621
- if (isFullyDefined(AndType (protoTp1, protoTp2), force)) protoTp1
622
- else instUndetMap.apply(protoTp1)
623
- }
624
- else {
625
- debug.println(s " $protoTp1 <:< $protoTp2 = false " )
626
- NoType
627
- }
628
- }
629
- }
630
-
631
479
/** Abstract sealed types, or-types, Boolean and Java enums can be decomposed */
632
480
def canDecompose (tp : Type ): Boolean = {
633
481
val dealiasedTp = tp.dealias
0 commit comments