From 61f897ccea4aa14f63152484db98ddccc549611a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 5 Oct 2017 07:57:15 +0200 Subject: [PATCH 1/3] Reorder pattern match based on frequency transformUnnamed total number of matches when compiling the dotty bootstrapped compiler (Apply,988737) (TypeTree,938211) (Thicket,314168) (This,258670) (Literal,207556) (Block,200439) (TypeApply,142962) (If,86724) (New,51117) (Typed,43350) (CaseDef,41226) (Closure,31121) (Assign,29101) (SeqLiteral,24646) (Super,19849) (Template,18180) (Match,11466) (default,10334) (UnApply,9327) (PackageDef,6392) (Try,1655) (Inlined,1528) (Return,1255) (Alternative,659) --- .../tools/dotc/transform/TreeTransform.scala | 188 +++++++++--------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala b/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala index 5bffd92da656..badfc0c3d920 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -974,13 +974,6 @@ object TreeTransforms { val qual = transform(tree.qualifier, mutatedInfo, cur) goSelect(cpy.Select(tree)(qual, tree.name), mutatedInfo.nx.nxTransSelect(cur)) } - case tree: Bind => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForBind, info.nx.nxPrepBind, tree, cur) - if (mutatedInfo eq null) tree - else { - val body = transform(tree.body, mutatedInfo, cur) - goBind(cpy.Bind(tree)(tree.name, body), mutatedInfo.nx.nxTransBind(cur)) - } case tree: ValDef if !tree.isEmpty => // As a result of discussing with Martin: emptyValDefs shouldn't be copied // NAME implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForValDef, info.nx.nxPrepValDef, tree, cur) if (mutatedInfo eq null) tree @@ -1008,23 +1001,19 @@ object TreeTransforms { val rhs = transform(tree.rhs, mutatedInfo, cur)(localContext(tree.symbol)) goTypeDef(cpy.TypeDef(tree)(tree.name, rhs), mutatedInfo.nx.nxTransTypeDef(cur)) } + case tree: Bind => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForBind, info.nx.nxPrepBind, tree, cur) + if (mutatedInfo eq null) tree + else { + val body = transform(tree.body, mutatedInfo, cur) + goBind(cpy.Bind(tree)(tree.name, body), mutatedInfo.nx.nxTransBind(cur)) + } case _ => tree } final private[TreeTransforms] def transformUnnamed(tree: Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = tree match { - case tree: This => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForThis, info.nx.nxPrepThis, tree, cur) - if (mutatedInfo eq null) tree - else goThis(tree, mutatedInfo.nx.nxTransThis(cur)) - case tree: Super => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSuper, info.nx.nxPrepSuper, tree, cur) - if (mutatedInfo eq null) tree - else { - val qual = transform(tree.qual, mutatedInfo, cur) - goSuper(cpy.Super(tree)(qual, tree.mix), mutatedInfo.nx.nxTransSuper(cur)) - } case tree: Apply => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForApply, info.nx.nxPrepApply, tree, cur) if (mutatedInfo eq null) tree @@ -1033,6 +1022,28 @@ object TreeTransforms { val args = transformSubTrees(tree.args, mutatedInfo, cur) goApply(cpy.Apply(tree)(fun, args), mutatedInfo.nx.nxTransApply(cur)) } + case tree: TypeTree => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeTree, info.nx.nxPrepTypeTree, tree, cur) + if (mutatedInfo eq null) tree + else goTypeTree(tree, mutatedInfo.nx.nxTransTypeTree(cur)) + case Thicket(trees) => + cpy.Thicket(tree)(transformTrees(trees, info, cur)) + case tree: This => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForThis, info.nx.nxPrepThis, tree, cur) + if (mutatedInfo eq null) tree + else goThis(tree, mutatedInfo.nx.nxTransThis(cur)) + case tree: Literal => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForLiteral, info.nx.nxPrepLiteral, tree, cur) + if (mutatedInfo eq null) tree + else goLiteral(tree, mutatedInfo.nx.nxTransLiteral(cur)) + case tree: Block => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForBlock, info.nx.nxPrepBlock, tree, cur) + if (mutatedInfo eq null) tree + else { + val stats = transformStats(tree.stats, ctx.owner, mutatedInfo, cur) + val expr = transform(tree.expr, mutatedInfo, cur) + goBlock(cpy.Block(tree)(stats, expr), mutatedInfo.nx.nxTransBlock(cur)) + } case tree: TypeApply => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeApply, info.nx.nxPrepTypeApply, tree, cur) if (mutatedInfo eq null) tree @@ -1041,10 +1052,15 @@ object TreeTransforms { val args = transformTrees(tree.args, mutatedInfo, cur) goTypeApply(cpy.TypeApply(tree)(fun, args), mutatedInfo.nx.nxTransTypeApply(cur)) } - case tree: Literal => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForLiteral, info.nx.nxPrepLiteral, tree, cur) + case tree: If => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForIf, info.nx.nxPrepIf, tree, cur) if (mutatedInfo eq null) tree - else goLiteral(tree, mutatedInfo.nx.nxTransLiteral(cur)) + else { + val cond = transform(tree.cond, mutatedInfo, cur) + val thenp = transform(tree.thenp, mutatedInfo, cur) + val elsep = transform(tree.elsep, mutatedInfo, cur) + goIf(cpy.If(tree)(cond, thenp, elsep), mutatedInfo.nx.nxTransIf(cur)) + } case tree: New => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForNew, info.nx.nxPrepNew, tree, cur) if (mutatedInfo eq null) tree @@ -1060,6 +1076,24 @@ object TreeTransforms { val tpt = transform(tree.tpt, mutatedInfo, cur) goTyped(cpy.Typed(tree)(expr, tpt), mutatedInfo.nx.nxTransTyped(cur)) } + case tree: CaseDef => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForCaseDef, info.nx.nxPrepCaseDef, tree, cur) + if (mutatedInfo eq null) tree + else { + val pat = transform(tree.pat, mutatedInfo, cur)(ctx.addMode(Mode.Pattern)) + val guard = transform(tree.guard, mutatedInfo, cur) + val body = transform(tree.body, mutatedInfo, cur) + goCaseDef(cpy.CaseDef(tree)(pat, guard, body), mutatedInfo.nx.nxTransCaseDef(cur)) + } + case tree: Closure => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForClosure, info.nx.nxPrepClosure, tree, cur) + if (mutatedInfo eq null) tree + else { + val env = transformTrees(tree.env, mutatedInfo, cur) + val meth = transform(tree.meth, mutatedInfo, cur) + val tpt = transform(tree.tpt, mutatedInfo, cur) + goClosure(cpy.Closure(tree)(env, meth, tpt), mutatedInfo.nx.nxTransClosure(cur)) + } case tree: Assign => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForAssign, info.nx.nxPrepAssign, tree, cur) if (mutatedInfo eq null) tree @@ -1068,31 +1102,30 @@ object TreeTransforms { val rhs = transform(tree.rhs, mutatedInfo, cur) goAssign(cpy.Assign(tree)(lhs, rhs), mutatedInfo.nx.nxTransAssign(cur)) } - case tree: Block => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForBlock, info.nx.nxPrepBlock, tree, cur) + case tree: SeqLiteral => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSeqLiteral, info.nx.nxPrepSeqLiteral, tree, cur) if (mutatedInfo eq null) tree else { - val stats = transformStats(tree.stats, ctx.owner, mutatedInfo, cur) - val expr = transform(tree.expr, mutatedInfo, cur) - goBlock(cpy.Block(tree)(stats, expr), mutatedInfo.nx.nxTransBlock(cur)) + val elems = transformTrees(tree.elems, mutatedInfo, cur) + val elemtpt = transform(tree.elemtpt, mutatedInfo, cur) + goSeqLiteral(cpy.SeqLiteral(tree)(elems, elemtpt), mutatedInfo.nx.nxTransSeqLiteral(cur)) } - case tree: If => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForIf, info.nx.nxPrepIf, tree, cur) + case tree: Super => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSuper, info.nx.nxPrepSuper, tree, cur) if (mutatedInfo eq null) tree else { - val cond = transform(tree.cond, mutatedInfo, cur) - val thenp = transform(tree.thenp, mutatedInfo, cur) - val elsep = transform(tree.elsep, mutatedInfo, cur) - goIf(cpy.If(tree)(cond, thenp, elsep), mutatedInfo.nx.nxTransIf(cur)) + val qual = transform(tree.qual, mutatedInfo, cur) + goSuper(cpy.Super(tree)(qual, tree.mix), mutatedInfo.nx.nxTransSuper(cur)) } - case tree: Closure => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForClosure, info.nx.nxPrepClosure, tree, cur) + case tree: Template => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTemplate, info.nx.nxPrepTemplate, tree, cur) if (mutatedInfo eq null) tree else { - val env = transformTrees(tree.env, mutatedInfo, cur) - val meth = transform(tree.meth, mutatedInfo, cur) - val tpt = transform(tree.tpt, mutatedInfo, cur) - goClosure(cpy.Closure(tree)(env, meth, tpt), mutatedInfo.nx.nxTransClosure(cur)) + val constr = transformSub(tree.constr, mutatedInfo, cur) + val parents = transformTrees(tree.parents, mutatedInfo, cur)(ctx.superCallContext) + val self = transformSub(tree.self, mutatedInfo, cur) + val body = transformStats(tree.body, tree.symbol, mutatedInfo, cur) + goTemplate(cpy.Template(tree)(constr, parents, self, body), mutatedInfo.nx.nxTransTemplate(cur)) } case tree: Match => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForMatch, info.nx.nxPrepMatch, tree, cur) @@ -1102,26 +1135,23 @@ object TreeTransforms { val cases = transformSubTrees(tree.cases, mutatedInfo, cur) goMatch(cpy.Match(tree)(selector, cases), mutatedInfo.nx.nxTransMatch(cur)) } - case tree: CaseDef => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForCaseDef, info.nx.nxPrepCaseDef, tree, cur) + case tree: UnApply => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForUnApply, info.nx.nxPrepUnApply, tree, cur) if (mutatedInfo eq null) tree else { - val pat = transform(tree.pat, mutatedInfo, cur)(ctx.addMode(Mode.Pattern)) - val guard = transform(tree.guard, mutatedInfo, cur) - val body = transform(tree.body, mutatedInfo, cur) - goCaseDef(cpy.CaseDef(tree)(pat, guard, body), mutatedInfo.nx.nxTransCaseDef(cur)) + val fun = transform(tree.fun, mutatedInfo, cur) + val implicits = transformTrees(tree.implicits, mutatedInfo, cur) + val patterns = transformTrees(tree.patterns, mutatedInfo, cur) + goUnApply(cpy.UnApply(tree)(fun, implicits, patterns), mutatedInfo.nx.nxTransUnApply(cur)) } - case tree: Return => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForReturn, info.nx.nxPrepReturn, tree, cur) + case tree: PackageDef => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForPackageDef, info.nx.nxPrepPackageDef, tree, cur) if (mutatedInfo eq null) tree else { - val expr = transform(tree.expr, mutatedInfo, cur) - val from = tree.from - // don't transform the `from` part, as this is not a normal ident, but - // a pointer to the enclosing method. Transforming this as a normal ident - // can go wrong easily. If a transformation is needed, it should be - // the responsibility of the transformReturn method to handle this also. - goReturn(cpy.Return(tree)(expr, from), mutatedInfo.nx.nxTransReturn(cur)) + val nestedCtx = localContext(tree.symbol) + val pid = transformSub(tree.pid, mutatedInfo, cur) + val stats = transformStats(tree.stats, tree.symbol, mutatedInfo, cur)(nestedCtx) + goPackageDef(cpy.PackageDef(tree)(pid, stats), mutatedInfo.nx.nxTransPackageDef(cur)) } case tree: Try => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTry, info.nx.nxPrepTry, tree, cur) @@ -1132,14 +1162,6 @@ object TreeTransforms { val finalizer = transform(tree.finalizer, mutatedInfo, cur) goTry(cpy.Try(tree)(block, cases1, finalizer), mutatedInfo.nx.nxTransTry(cur)) } - case tree: SeqLiteral => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSeqLiteral, info.nx.nxPrepSeqLiteral, tree, cur) - if (mutatedInfo eq null) tree - else { - val elems = transformTrees(tree.elems, mutatedInfo, cur) - val elemtpt = transform(tree.elemtpt, mutatedInfo, cur) - goSeqLiteral(cpy.SeqLiteral(tree)(elems, elemtpt), mutatedInfo.nx.nxTransSeqLiteral(cur)) - } case tree: Inlined => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForInlined, info.nx.nxPrepInlined, tree, cur) if (mutatedInfo eq null) tree @@ -1148,10 +1170,18 @@ object TreeTransforms { val expansion = transform(tree.expansion, mutatedInfo, cur)(inlineContext(tree)) goInlined(cpy.Inlined(tree)(tree.call, bindings, expansion), mutatedInfo.nx.nxTransInlined(cur)) } - case tree: TypeTree => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeTree, info.nx.nxPrepTypeTree, tree, cur) + case tree: Return => + implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForReturn, info.nx.nxPrepReturn, tree, cur) if (mutatedInfo eq null) tree - else goTypeTree(tree, mutatedInfo.nx.nxTransTypeTree(cur)) + else { + val expr = transform(tree.expr, mutatedInfo, cur) + val from = tree.from + // don't transform the `from` part, as this is not a normal ident, but + // a pointer to the enclosing method. Transforming this as a normal ident + // can go wrong easily. If a transformation is needed, it should be + // the responsibility of the transformReturn method to handle this also. + goReturn(cpy.Return(tree)(expr, from), mutatedInfo.nx.nxTransReturn(cur)) + } case tree: Alternative => implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForAlternative, info.nx.nxPrepAlternative, tree, cur) if (mutatedInfo eq null) tree @@ -1159,36 +1189,6 @@ object TreeTransforms { val trees = transformTrees(tree.trees, mutatedInfo, cur) goAlternative(cpy.Alternative(tree)(trees), mutatedInfo.nx.nxTransAlternative(cur)) } - case tree: UnApply => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForUnApply, info.nx.nxPrepUnApply, tree, cur) - if (mutatedInfo eq null) tree - else { - val fun = transform(tree.fun, mutatedInfo, cur) - val implicits = transformTrees(tree.implicits, mutatedInfo, cur) - val patterns = transformTrees(tree.patterns, mutatedInfo, cur) - goUnApply(cpy.UnApply(tree)(fun, implicits, patterns), mutatedInfo.nx.nxTransUnApply(cur)) - } - case tree: Template => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTemplate, info.nx.nxPrepTemplate, tree, cur) - if (mutatedInfo eq null) tree - else { - val constr = transformSub(tree.constr, mutatedInfo, cur) - val parents = transformTrees(tree.parents, mutatedInfo, cur)(ctx.superCallContext) - val self = transformSub(tree.self, mutatedInfo, cur) - val body = transformStats(tree.body, tree.symbol, mutatedInfo, cur) - goTemplate(cpy.Template(tree)(constr, parents, self, body), mutatedInfo.nx.nxTransTemplate(cur)) - } - case tree: PackageDef => - implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForPackageDef, info.nx.nxPrepPackageDef, tree, cur) - if (mutatedInfo eq null) tree - else { - val nestedCtx = localContext(tree.symbol) - val pid = transformSub(tree.pid, mutatedInfo, cur) - val stats = transformStats(tree.stats, tree.symbol, mutatedInfo, cur)(nestedCtx) - goPackageDef(cpy.PackageDef(tree)(pid, stats), mutatedInfo.nx.nxTransPackageDef(cur)) - } - case Thicket(trees) => - cpy.Thicket(tree)(transformTrees(trees, info, cur)) case tree => implicit val originalInfo: TransformerInfo = info goOther(tree, info.nx.nxTransOther(cur)) From 57661eeaae3f8984b4c56916ea43f525ed3891db Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 5 Oct 2017 22:37:29 +0200 Subject: [PATCH 2/3] Reorder pattern match based on frequency foldOver total number of matches when compiling the dotty bootstrapped compiler (TypeRef,880390) (AppliedType,276595) (BoundType,122879) (ThisType,117388) (LambdaType,95690) (NoPrefix,94493) (TermRef,88508) (TypeVar,30322) (ExprType,16702) (TypeBounds,16432) (AndOrType,6234) (AnnotatedType,5948) (default,5252) (ProtoType,4044) (RefinedType,3270) (WildcardType,2064) (ClassInfo,1520) (JavaArrayType,516) (SkolemType,210) (TypeArgRef,98) (SuperType,77) (LazyRef,3) --- .../src/dotty/tools/dotc/core/Types.scala | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 54c3113ddfe0..8252b86cb30b 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4198,13 +4198,6 @@ object Types { val tp1 = tp.prefix.lookupRefined(tp.name) if (tp1.exists) this(x, tp1) else applyToPrefix(x, tp) } - case tp: TermRef => - if (stopAtStatic && tp.currentSymbol.isStatic) x - else applyToPrefix(x, tp) - - case _: ThisType - | _: BoundType - | NoPrefix => x case tp @ AppliedType(tycon, args) => @tailrec def foldArgs(x: T, tparams: List[ParamInfo], args: List[Type]): T = @@ -4222,8 +4215,25 @@ object Types { } foldArgs(this(x, tycon), tp.typeParams, args) - case tp: RefinedType => - this(this(x, tp.parent), tp.refinedInfo) + case _: BoundType | _: ThisType => x + + case tp: LambdaType => + variance = -variance + val y = foldOver(x, tp.paramInfos) + variance = -variance + this(y, tp.resultType) + + case NoPrefix => x + + case tp: TermRef => + if (stopAtStatic && tp.currentSymbol.isStatic) x + else applyToPrefix(x, tp) + + case tp: TypeVar => + this(x, tp.underlying) + + case ExprType(restpe) => + this(x, restpe) case bounds @ TypeBounds(lo, hi) => if (lo eq hi) atVariance(0)(this(x, lo)) @@ -4234,29 +4244,26 @@ object Types { this(y, hi) } - case tp: RecType => - this(x, tp.parent) + case tp: AndOrType => + this(this(x, tp.tp1), tp.tp2) - case ExprType(restpe) => - this(x, restpe) + case AnnotatedType(underlying, annot) => + this(applyToAnnot(x, annot), underlying) - case tp: TypeVar => - this(x, tp.underlying) + case tp: ProtoType => + tp.fold(x, this) - case SuperType(thistp, supertp) => - this(this(x, thistp), supertp) + case tp: RefinedType => + this(this(x, tp.parent), tp.refinedInfo) + + case tp: WildcardType => + this(x, tp.optBounds) case tp @ ClassInfo(prefix, _, _, _, _) => this(x, prefix) - case tp: LambdaType => - variance = -variance - val y = foldOver(x, tp.paramInfos) - variance = -variance - this(y, tp.resultType) - - case tp: AndOrType => - this(this(x, tp.tp1), tp.tp2) + case tp: JavaArrayType => + this(x, tp.elemType) case tp: SkolemType => this(x, tp.info) @@ -4264,20 +4271,14 @@ object Types { case tp @ TypeArgRef(prefix, _, _) => atVariance(0)(this(x, prefix)) - case AnnotatedType(underlying, annot) => - this(applyToAnnot(x, annot), underlying) - - case tp: WildcardType => - this(x, tp.optBounds) - - case tp: JavaArrayType => - this(x, tp.elemType) + case SuperType(thistp, supertp) => + this(this(x, thistp), supertp) case tp: LazyRef => this(x, tp.ref) - case tp: ProtoType => - tp.fold(x, this) + case tp: RecType => + this(x, tp.parent) case _ => x }} From 4fb04d3af83e3a48b306df671c19876446a5eb34 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 6 Oct 2017 08:29:15 +0200 Subject: [PATCH 3/3] Reorder pattern match based on frequency NamedPartsAccumulator.apply total number of matches when compiling the dotty bootstrapped compiler (TypeRef,255627) (ThisType,128253) (NoPrefix,67972) (TermRef,33240) (AppliedType,22874) (default,13428) (TypeBounds,5013) (ParamRef,3931) (ConstantType,1893) --- compiler/src/dotty/tools/dotc/core/Types.scala | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 8252b86cb30b..62c9289a7b6c 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4315,19 +4315,23 @@ object Types { else { seen += tp tp match { - case tp: TermRef => - apply(foldOver(maybeAdd(x, tp), tp), tp.underlying) case tp: TypeRef => foldOver(maybeAdd(x, tp), tp) + case tp: ThisType => + apply(x, tp.tref) + case NoPrefix => + foldOver(x, tp) + case tp: TermRef => + apply(foldOver(maybeAdd(x, tp), tp), tp.underlying) + case tp: AppliedType => + foldOver(x, tp) case TypeBounds(lo, hi) => if (!excludeLowerBounds) apply(x, lo) apply(x, hi) - case tp: ThisType => - apply(x, tp.tref) - case tp: ConstantType => - apply(x, tp.underlying) case tp: ParamRef => apply(x, tp.underlying) + case tp: ConstantType => + apply(x, tp.underlying) case _ => foldOver(x, tp) }