Skip to content

[WIP] Change HK encoding #1282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 86 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
468b499
Record binding kind in TypeBounds
odersky May 24, 2016
2d8d291
Allow refinements of new types
odersky May 24, 2016
10ef004
Allow general recursion in refined types.
odersky May 25, 2016
3c99610
Refinements to refinement types
odersky May 25, 2016
461fe3d
Add type lambdas
odersky May 26, 2016
3960710
Better printing of skolems
odersky May 26, 2016
a3a6108
New type lambda scheme for hk types
odersky May 26, 2016
e768331
Add mapInfo method to Denotations
odersky May 27, 2016
c7fa021
Introduce recursive types
odersky May 27, 2016
7d3b4de
Use recursive types also when unpickling from Scala 2.x
odersky May 27, 2016
96f6bc6
Abstract type parameters out from type symbols
odersky May 27, 2016
4b912db
Fix toVariance in MemberBinding
odersky May 27, 2016
6b9e7d8
Disable checkInst in RecType
odersky May 27, 2016
67b4917
Simplify RecType.closeOver
odersky May 27, 2016
7c59785
Rename MemberInfo -> MemberBinding
odersky May 27, 2016
7a92cd5
Add printing of type lambda trees
odersky May 27, 2016
c9daca0
Replace MemberBinding # memberInfo by memberBounds
odersky May 27, 2016
ddc3a81
Fix printing of type lambdas
odersky May 27, 2016
eb3f1a6
Remove special case in parser
odersky May 27, 2016
b6f9305
[WIP] Tenantive new HK scheme.
odersky May 30, 2016
444e182
Avoid crasher in derivedTypeParams
odersky May 31, 2016
bc51e63
Fix printing of type lambdas
odersky May 31, 2016
b1ee403
Remove printlns
odersky May 31, 2016
fed3150
Revise logic in type comparer for new HK scheme
odersky May 31, 2016
56d2dd3
Rmove over-zealous check
odersky May 31, 2016
828b231
Turn on new hk scheme
odersky Jun 1, 2016
ec0ce3a
Swap order of tests in lookupRefined
odersky Jun 1, 2016
e17ca87
Change joins of BindingKinds
odersky Jun 1, 2016
a7fb8a7
Fix printing of type lambdas under new hk scheme
odersky Jun 2, 2016
cd51707
refine isRef for hk type
odersky Jun 2, 2016
88f4272
Fix withBindingKind for type aliases
odersky Jun 2, 2016
df73535
Multiple fixes to BetaReduce
odersky Jun 2, 2016
a0afd49
Fix logic for hk subtype tests
odersky Jun 2, 2016
cbf52d1
Make isHK more precise
odersky Jun 2, 2016
e433fe9
Beta-reduce when simplifying
odersky Jun 2, 2016
0de8705
Make etaExpandIfHk work for non-symbol type params
odersky Jun 2, 2016
7d8457d
Avoid stackoverflows for `Rep[T] = T`.
odersky Jun 2, 2016
06f916e
Refinement of cycle avoidance
odersky Jun 3, 2016
194f5d3
Don't map info of SkolemTypes in type maps
odersky Jun 3, 2016
1a656a1
Handle LazyRefs in BetaReduce
odersky Jun 3, 2016
c4fc98b
Fix^2 of asMemberOf
odersky Jun 3, 2016
5ea78e4
Try to beta-reduce bounds before adding to a constraint.
odersky Jun 3, 2016
8fd0e0f
More subtle handling of LazyRefs in BetaReduce
odersky Jun 4, 2016
8eb98a8
Another refinement to asMemberOf
odersky Jun 4, 2016
6068e7a
Drop isSafe test from BetaReduce
odersky Jun 4, 2016
20ebc13
Normalize RecTypes on creation to avoid cycles.
odersky Jun 4, 2016
6afe257
Add a second betaReduce
odersky Jun 4, 2016
1255fb8
Adapt widenForMatchSelector to new HK scheme
odersky Jun 5, 2016
bdf7f3e
Fix typeParams for abstract types under completion
odersky Jun 5, 2016
d5771da
Swap subtype tests
odersky Jun 6, 2016
9e14d74
Make underlyingClassRef work for hk types under new scheme.
odersky Jun 6, 2016
76f7563
Esnure that toAvoid does not creat hk from * types
odersky Jun 6, 2016
2b70615
Let getClass return a * type
odersky Jun 6, 2016
757f117
Generalize typeParamSymbols
odersky Jun 6, 2016
55ff0b5
Eta-expand unapplied types that have type parameters
odersky Jun 6, 2016
ec11b0b
Check kinds of type parameters
odersky Jun 6, 2016
de29cd1
Restrict betaReduce to hk applications
odersky Jun 6, 2016
9b21b46
Handle LazyRefs conservatively in isReferredTo
odersky Jun 7, 2016
226cdb9
Optionally, check kinds match for & and |
odersky Jun 7, 2016
7329957
Avoid infinite recursion when comparing recursive types.
odersky Jun 7, 2016
6fac433
Remove debug println
odersky Jun 7, 2016
6ed6857
Make typeParams more defensive
odersky Jun 7, 2016
7dc3135
Fix condition for lambda abstracting in Namer
odersky Jun 7, 2016
c896a83
Refinement for knownHK for PolyParams
odersky Jun 7, 2016
e38541b
Remove debug println
odersky Jun 7, 2016
db4d934
Make TypeAccumulators follow LazyRefs
odersky Jun 7, 2016
3560e56
Add normalizeHkApply to homogenize
odersky Jun 8, 2016
1844c1d
Avoid creating dependent function types for closures
odersky Jun 8, 2016
a6caf1c
Generalize compareHkApply to types other than PolyParams
odersky Jun 8, 2016
392090a
Homogenize skolem types
odersky Jun 8, 2016
5182a58
Change test to make it pass
odersky Jun 8, 2016
5e448ff
Disable named parameter tests
odersky Jun 8, 2016
5a20984
Fix merge errors
odersky Jun 8, 2016
9887c43
Revert "Generalize compareHkApply to types other than PolyParams"
odersky Jun 9, 2016
b4f21d0
Deal with nested findMember calls over the same RecType
odersky Jun 9, 2016
7cc0308
Add explanation why generizing compreHkApply is not needed.
odersky Jun 9, 2016
b88cfec
Fix comments
odersky Jun 9, 2016
7abd0cc
Add TODO comment in TreePickler
odersky Jun 9, 2016
794bb02
Swap order of subtype tests
odersky Jun 9, 2016
7c99c8a
Cleanups
odersky Jun 10, 2016
4c51505
Smarter handling of LazyRefs in betaReduce
odersky Jun 10, 2016
eb6cfb4
Optimize RecType/RecType comparisons
odersky Jun 10, 2016
6d6afbf
Fi compareHkLambda
odersky Jun 11, 2016
745a718
Remove old hk scheme
odersky Jun 11, 2016
79a7976
Simoplify RefinedType
odersky Jun 11, 2016
57bf237
Simplify typeParams
odersky Jun 12, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/SyntaxSummary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ grammar.
ClassQualifier ::= `[' id `]'

Type ::= FunArgTypes `=>' Type Function(ts, t)
| HkTypeParamClause `->' Type TypeLambda(ps, t)
| InfixType
FunArgTypes ::= InfixType
| `(' [ FunArgType {`,' FunArgType } ] `)'
Expand Down Expand Up @@ -125,7 +126,6 @@ grammar.
TypeParamBounds ::= TypeBounds {`<%' Type} {`:' Type} ContextBounds(typeBounds, tps)

Expr ::= FunParams `=>' Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr)
| Expr1
FunParams ::= Bindings
| [`implicit'] id
| `_'
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ object desugar {
val relocate = new TypeMap {
val originalOwner = sym.owner
def apply(tp: Type) = tp match {
case tp: NamedType if tp.symbol.owner eq originalOwner =>
case tp: NamedType if tp.symbol.exists && (tp.symbol.owner eq originalOwner) =>
val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next
var local = defctx.denotNamed(tp.name).suchThat(_ is ParamOrAccessor).symbol
if (local.exists) (defctx.owner.thisType select local).dealias
Expand Down
16 changes: 16 additions & 0 deletions src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,12 @@ object Trees {
def forwardTo = tpt
}

/** [typeparams] -> tpt */
case class TypeLambdaTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])
extends TypTree[T] {
type ThisTree[-T >: Untyped] = TypeLambdaTree[T]
}

/** => T */
case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])
extends TypTree[T] {
Expand Down Expand Up @@ -851,6 +857,7 @@ object Trees {
type OrTypeTree = Trees.OrTypeTree[T]
type RefinedTypeTree = Trees.RefinedTypeTree[T]
type AppliedTypeTree = Trees.AppliedTypeTree[T]
type TypeLambdaTree = Trees.TypeLambdaTree[T]
type ByNameTypeTree = Trees.ByNameTypeTree[T]
type TypeBoundsTree = Trees.TypeBoundsTree[T]
type Bind = Trees.Bind[T]
Expand Down Expand Up @@ -1028,6 +1035,10 @@ object Trees {
case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree
case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args))
}
def TypeLambdaTree(tree: Tree)(tparams: List[TypeDef], body: Tree): TypeLambdaTree = tree match {
case tree: TypeLambdaTree if (tparams eq tree.tparams) && (body eq tree.body) => tree
case _ => finalize(tree, untpd.TypeLambdaTree(tparams, body))
}
def ByNameTypeTree(tree: Tree)(result: Tree): ByNameTypeTree = tree match {
case tree: ByNameTypeTree if result eq tree.result => tree
case _ => finalize(tree, untpd.ByNameTypeTree(result))
Expand Down Expand Up @@ -1160,6 +1171,8 @@ object Trees {
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
case AppliedTypeTree(tpt, args) =>
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
case TypeLambdaTree(tparams, body) =>
cpy.TypeLambdaTree(tree)(transformSub(tparams), transform(body))
case ByNameTypeTree(result) =>
cpy.ByNameTypeTree(tree)(transform(result))
case TypeBoundsTree(lo, hi) =>
Expand Down Expand Up @@ -1264,6 +1277,9 @@ object Trees {
this(this(x, tpt), refinements)
case AppliedTypeTree(tpt, args) =>
this(this(x, tpt), args)
case TypeLambdaTree(tparams, body) =>
implicit val ctx: Context = localCtx
this(this(x, tparams), body)
case ByNameTypeTree(result) =>
this(x, result)
case TypeBoundsTree(lo, hi) =>
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
private def ta(implicit ctx: Context) = ctx.typeAssigner

def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = Modifiers(
sym.flags & ModifierFlags,
sym.flags & (if (sym.isType) ModifierFlags | VarianceFlags else ModifierFlags),
if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
sym.annotations map (_.tree))

Expand Down
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right)
def RefinedTypeTree(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = new RefinedTypeTree(tpt, refinements)
def AppliedTypeTree(tpt: Tree, args: List[Tree]): AppliedTypeTree = new AppliedTypeTree(tpt, args)
def TypeLambdaTree(tparams: List[TypeDef], body: Tree): TypeLambdaTree = new TypeLambdaTree(tparams, body)
def ByNameTypeTree(result: Tree): ByNameTypeTree = new ByNameTypeTree(result)
def TypeBoundsTree(lo: Tree, hi: Tree): TypeBoundsTree = new TypeBoundsTree(lo, hi)
def Bind(name: Name, body: Tree): Bind = new Bind(name, body)
Expand Down
5 changes: 5 additions & 0 deletions src/dotty/tools/dotc/config/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ object Config {
*/
final val checkProjections = false

/** If this flag is set it is checked that &/| only apply to types
* that are either both hk types or both * types.
*/
final val checkKinds = true

/** The recursion depth for showing a summarized string */
final val summarizeDepth = 2

Expand Down
4 changes: 4 additions & 0 deletions src/dotty/tools/dotc/core/ConstraintHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ trait ConstraintHandling {
def addParamBound(bound: PolyParam) =
if (fromBelow) addLess(bound, param) else addLess(param, bound)

assert(param.isHK == bound.isHK, s"$param / $bound / $fromBelow")

/** Drop all constrained parameters that occur at the toplevel in `bound` and
* handle them by `addLess` calls.
* The preconditions make sure that such parameters occur only
Expand Down Expand Up @@ -285,6 +287,8 @@ trait ConstraintHandling {
if (!addParamBound(bound)) NoType
else if (fromBelow) defn.NothingType
else defn.AnyType
case bound: RefinedType =>
bound.normalizeHkApply
case _ =>
bound
}
Expand Down
67 changes: 1 addition & 66 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ class Definitions {
lazy val Any_hashCode = newMethod(AnyClass, nme.hashCode_, MethodType(Nil, IntType))
lazy val Any_toString = newMethod(AnyClass, nme.toString_, MethodType(Nil, StringType))
lazy val Any_## = newMethod(AnyClass, nme.HASHHASH, ExprType(IntType), Final)
lazy val Any_getClass = newMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef), Final)
lazy val Any_getClass = newMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
lazy val Any_isInstanceOf = newT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
lazy val Any_asInstanceOf = newT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, PolyParam(_, 0), Final)

Expand Down Expand Up @@ -663,71 +663,6 @@ class Definitions {

def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1

// ----- LambdaXYZ traits ------------------------------------------

private var myLambdaTraits: Set[Symbol] = Set()

/** The set of HigherKindedXYZ traits encountered so far */
def lambdaTraits: Set[Symbol] = myLambdaTraits

private var LambdaTraitForVariances = mutable.Map[List[Int], ClassSymbol]()

/** The HigherKinded trait corresponding to symbols `boundSyms` (which are assumed
* to be the type parameters of a higher-kided type). This is a class symbol that
* would be generated by the following schema.
*
* trait LambdaXYZ extends Object with P1 with ... with Pn {
* type v_1 hk$0; ...; type v_N hk$N;
* type +$Apply
* }
*
* Here:
*
* - v_i are the variances of the bound symbols (i.e. +, -, or empty).
* - XYZ is a string of length N with one letter for each variant of a bound symbol,
* using `P` (positive variance), `N` (negative variance), `I` (invariant).
* - for each positive or negative variance v_i there is a parent trait Pj which
* is the same as LambdaXYZ except that it has `I` in i-th position.
*/
def LambdaTrait(vcs: List[Int]): ClassSymbol = {
assert(vcs.nonEmpty)

def varianceFlags(v: Int) = v match {
case -1 => Contravariant
case 0 => EmptyFlags
case 1 => Covariant
}

val completer = new LazyType {
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
val cls = denot.asClass.classSymbol
val paramDecls = newScope
for (i <- 0 until vcs.length)
newTypeParam(cls, tpnme.hkArg(i), varianceFlags(vcs(i)), paramDecls)
newTypeField(cls, tpnme.hkApply, Covariant, paramDecls)
val parentTraitRefs =
for (i <- 0 until vcs.length if vcs(i) != 0)
yield LambdaTrait(vcs.updated(i, 0)).typeRef
denot.info = ClassInfo(
ScalaPackageClass.thisType, cls, ObjectClass.typeRef :: parentTraitRefs.toList, paramDecls)
}
}

val traitName = tpnme.hkLambda(vcs)

def createTrait = {
val cls = newClassSymbol(
ScalaPackageClass,
traitName,
PureInterfaceCreationFlags | Synthetic,
completer)
myLambdaTraits += cls
cls
}

LambdaTraitForVariances.getOrElseUpdate(vcs, createTrait)
}

// ----- primitive value class machinery ------------------------------------------

/** This class would also be obviated by the implicit function type design */
Expand Down
10 changes: 9 additions & 1 deletion src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ object Denotations {
/** Is this denotation different from NoDenotation or an ErrorDenotation? */
def exists: Boolean = true

/** A denotation with the info of this denotation transformed using `f` */
def mapInfo(f: Type => Type)(implicit ctx: Context): Denotation

/** If this denotation does not exist, fallback to alternative */
final def orElse(that: => Denotation) = if (this.exists) this else that

Expand Down Expand Up @@ -242,7 +245,7 @@ object Denotations {
}
else if (exists && !qualifies(symbol)) NoDenotation
else asSingleDenotation
}
}

/** Form a denotation by conjoining with denotation `that`.
*
Expand Down Expand Up @@ -456,6 +459,8 @@ object Denotations {
else if (!d2.exists) d1
else derivedMultiDenotation(d1, d2)
}
def mapInfo(f: Type => Type)(implicit ctx: Context): Denotation =
derivedMultiDenotation(denot1.mapInfo(f), denot2.mapInfo(f))
def derivedMultiDenotation(d1: Denotation, d2: Denotation) =
if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2)
override def toString = alternatives.mkString(" <and> ")
Expand Down Expand Up @@ -488,6 +493,9 @@ object Denotations {
if ((symbol eq this.symbol) && (info eq this.info)) this
else newLikeThis(symbol, info)

def mapInfo(f: Type => Type)(implicit ctx: Context): SingleDenotation =
derivedSingleDenotation(symbol, f(info))

def orElse(that: => SingleDenotation) = if (this.exists) this else that

def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
Expand Down
3 changes: 2 additions & 1 deletion src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,8 @@ object Flags {

/** Flags representing modifiers that can appear in trees */
final val ModifierFlags =
SourceModifierFlags | Module | Param | Synthetic | Package | Local | commonFlags(Mutable)
SourceModifierFlags | Module | Param | Synthetic | Package | Local |
commonFlags(Mutable)
// | Trait is subsumed by commonFlags(Lazy) from SourceModifierFlags

assert(ModifierFlags.isTermFlags && ModifierFlags.isTypeFlags)
Expand Down
34 changes: 34 additions & 0 deletions src/dotty/tools/dotc/core/MemberBinding.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package dotty.tools.dotc.core

import Names.Name
import Contexts.Context
import Types.{Type, TypeBounds}

/** A common super trait of Symbol and Refinement.
* Used to capture the attributes of type parameters
* which can be implemented as either symbols or refinements.
*/
trait MemberBinding {

/** Does this binding represent a type parameter?
* Only in that case the rest of the binding's methods are significant.
*/
def isTypeParam(implicit ctx: Context): Boolean

/** The name of the member */
def memberName(implicit ctx: Context): Name

/** The info of the member */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that a more accurate description would be "The bounds of the type parameter
@pre isTypeParam = true"

def memberBounds(implicit ctx: Context): TypeBounds

/** The info of the member as seen from a prefix type.
* This can be different from `memberInfo` if the binding
* is a type symbol of a class.
*/
def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds

/** The variance of the type parameter
* @pre: isTypeParam = true
*/
def memberVariance(implicit ctx: Context): Int
}
8 changes: 0 additions & 8 deletions src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,6 @@ object NameOps {
def hkArgIndex: Int =
name.drop(tpnme.hkArgPrefixLength).toString.toInt

def isLambdaTraitName(implicit ctx: Context): Boolean =
name.isTypeName && name.startsWith(tpnme.hkLambdaPrefix)

def lambdaTraitVariances(implicit ctx: Context): List[Int] = {
val vs = name.drop(tpnme.hkLambdaPrefix.length)
vs.toList.map(c => tpnme.varianceSuffixes.indexOf(c) - 1)
}

/** If the name ends with $nn where nn are
* all digits, strip the $ and the digits.
* Otherwise return the argument.
Expand Down
6 changes: 0 additions & 6 deletions src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -529,9 +529,7 @@ object StdNames {

val synthSwitch: N = "$synthSwitch"

val hkApply: N = "$Apply"
val hkArgPrefix: N = "$hk"
val hkLambdaPrefix: N = "Lambda$"
val hkArgPrefixHead: Char = hkArgPrefix.head
val hkArgPrefixLength: Int = hkArgPrefix.length

Expand Down Expand Up @@ -744,12 +742,8 @@ object StdNames {
def syntheticTypeParamNames(num: Int): List[TypeName] =
(0 until num).map(syntheticTypeParamName)(breakOut)

def hkLambda(vcs: List[Int]): TypeName = hkLambdaPrefix ++ vcs.map(varianceSuffix).mkString
def hkArg(n: Int): TypeName = hkArgPrefix ++ n.toString

def varianceSuffix(v: Int): Char = varianceSuffixes.charAt(v + 1)
val varianceSuffixes = "NIP"

final val Conforms = encode("<:<")
}

Expand Down
16 changes: 8 additions & 8 deletions src/dotty/tools/dotc/core/Substituters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,21 +179,21 @@ trait Substituters { this: Context =>
.mapOver(tp)
}

final def substRefinedThis(tp: Type, from: Type, to: Type, theMap: SubstRefinedThisMap): Type =
final def substRecThis(tp: Type, from: Type, to: Type, theMap: SubstRecThisMap): Type =
tp match {
case tp @ RefinedThis(binder) =>
case tp @ RecThis(binder) =>
if (binder eq from) to else tp
case tp: NamedType =>
if (tp.currentSymbol.isStatic) tp
else tp.derivedSelect(substRefinedThis(tp.prefix, from, to, theMap))
else tp.derivedSelect(substRecThis(tp.prefix, from, to, theMap))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
tp.derivedRefinedType(substRefinedThis(tp.parent, from, to, theMap), tp.refinedName, substRefinedThis(tp.refinedInfo, from, to, theMap))
tp.derivedRefinedType(substRecThis(tp.parent, from, to, theMap), tp.refinedName, substRecThis(tp.refinedInfo, from, to, theMap))
case tp: TypeAlias =>
tp.derivedTypeAlias(substRefinedThis(tp.alias, from, to, theMap))
tp.derivedTypeAlias(substRecThis(tp.alias, from, to, theMap))
case _ =>
(if (theMap != null) theMap else new SubstRefinedThisMap(from, to))
(if (theMap != null) theMap else new SubstRecThisMap(from, to))
.mapOver(tp)
}

Expand Down Expand Up @@ -266,8 +266,8 @@ trait Substituters { this: Context =>
def apply(tp: Type): Type = substThis(tp, from, to, this)
}

final class SubstRefinedThisMap(from: Type, to: Type) extends DeepTypeMap {
def apply(tp: Type): Type = substRefinedThis(tp, from, to, this)
final class SubstRecThisMap(from: Type, to: Type) extends DeepTypeMap {
def apply(tp: Type): Type = substRecThis(tp, from, to, this)
}

final class SubstParamMap(from: ParamType, to: Type) extends DeepTypeMap {
Expand Down
Loading