Skip to content

Allocate fewer TypeMaps and TypeAccumulators #9618

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

Merged
merged 5 commits into from
Aug 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 11 additions & 11 deletions compiler/src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ object Decorators {
def & (ys: List[T]): List[T] = xs filter (ys contains _)
}

extension [T, U](xss: List[List[T]]):
extension [T, U](xss: List[List[T]])
def nestedMap(f: T => U): List[List[U]] =
xss.map(_.map(f))
def nestedMapConserve(f: T => U): List[List[U]] =
Expand All @@ -180,14 +180,14 @@ object Decorators {
xss.zipWithConserve(yss)((xs, ys) => xs.zipWithConserve(ys)(f))
end extension

extension (text: Text):
extension (text: Text)
def show(using Context): String = text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value)

/** Test whether a list of strings representing phases contains
* a given phase. See [[config.CompilerCommand#explainAdvanced]] for the
* exact meaning of "contains" here.
*/
extension (names: List[String]) {
extension (names: List[String])
def containsPhase(phase: Phase): Boolean =
names.nonEmpty && {
phase match {
Expand All @@ -203,18 +203,16 @@ object Decorators {
}
}
}
}

extension [T](x: T) {
extension [T](x: T)
def reporting(
op: WrappedResult[T] ?=> String,
printer: config.Printers.Printer = config.Printers.default): T = {
printer.println(op(using WrappedResult(x)))
x
}
}

extension [T](x: T) {
extension [T](x: T)
def assertingErrorsReported(using Context): T = {
assert(ctx.reporter.errorsReported)
x
Expand All @@ -223,9 +221,12 @@ object Decorators {
assert(ctx.reporter.errorsReported, msg)
x
}
}

extension (sc: StringContext) {
extension [T <: AnyRef](xs: ::[T])
def derivedCons(x1: T, xs1: List[T]) =
if (xs.head eq x1) && (xs.tail eq xs1) then xs else x1 :: xs1

extension (sc: StringContext)
/** General purpose string formatting */
def i(args: Any*)(using Context): String =
new StringFormatter(sc).assemble(args)
Expand All @@ -241,9 +242,8 @@ object Decorators {
*/
def ex(args: Any*)(using Context): String =
explained(em(args: _*))
}

extension [T <: AnyRef](arr: Array[T]):
extension [T <: AnyRef](arr: Array[T])
def binarySearch(x: T): Int = java.util.Arrays.binarySearch(arr.asInstanceOf[Array[Object]], x)

}
Expand Down
26 changes: 15 additions & 11 deletions compiler/src/dotty/tools/dotc/core/Substituters.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dotty.tools.dotc.core

import Types._, Symbols._, Contexts._
import Types._, Symbols._, Contexts._, Decorators._

/** Substitution operations on types. See the corresponding `subst` and
* `substThis` methods on class Type for an explanation.
Expand All @@ -16,6 +16,8 @@ object Substituters:
else tp.derivedSelect(subst(tp.prefix, from, to, theMap))
case _: ThisType =>
tp
case tp: AppliedType =>
tp.map(subst(_, from, to, theMap))
case _ =>
(if (theMap != null) theMap else new SubstBindingMap(from, to))
.mapOver(tp)
Expand Down Expand Up @@ -94,7 +96,7 @@ object Substituters:
ts = ts.tail
}
tp
case _: ThisType | _: BoundType =>
case _: BoundType =>
tp
case _ =>
(if (theMap != null) theMap else new SubstSymMap(from, to))
Expand Down Expand Up @@ -152,45 +154,47 @@ object Substituters:
else tp.derivedSelect(substParams(tp.prefix, from, to, theMap))
case _: ThisType =>
tp
case tp: AppliedType =>
tp.map(substParams(_, from, to, theMap))
case _ =>
(if (theMap != null) theMap else new SubstParamsMap(from, to))
.mapOver(tp)
}

final class SubstBindingMap(from: BindingType, to: BindingType)(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = subst(tp, from, to, this)
def apply(tp: Type): Type = subst(tp, from, to, this)(using mapCtx)
}

final class Subst1Map(from: Symbol, to: Type)(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = subst1(tp, from, to, this)
def apply(tp: Type): Type = subst1(tp, from, to, this)(using mapCtx)
}

final class Subst2Map(from1: Symbol, to1: Type, from2: Symbol, to2: Type)(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = subst2(tp, from1, to1, from2, to2, this)
def apply(tp: Type): Type = subst2(tp, from1, to1, from2, to2, this)(using mapCtx)
}

final class SubstMap(from: List[Symbol], to: List[Type])(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = subst(tp, from, to, this)
def apply(tp: Type): Type = subst(tp, from, to, this)(using mapCtx)
}

final class SubstSymMap(from: List[Symbol], to: List[Symbol])(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = substSym(tp, from, to, this)
def apply(tp: Type): Type = substSym(tp, from, to, this)(using mapCtx)
}

final class SubstThisMap(from: ClassSymbol, to: Type)(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = substThis(tp, from, to, this)
def apply(tp: Type): Type = substThis(tp, from, to, this)(using mapCtx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it mean all classes that inherit TypeMap (e.g. DeepTypeMap, ApproximatingTypeMap and AsSeenFromMap) have to write using mapCtx explicitly everywhere?

}

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

final class SubstParamMap(from: ParamRef, to: Type)(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = substParam(tp, from, to, this)
def apply(tp: Type): Type = substParam(tp, from, to, this)(using mapCtx)
}

final class SubstParamsMap(from: BindingType, to: List[Type])(using Context) extends DeepTypeMap {
def apply(tp: Type): Type = substParams(tp, from, to, this)
def apply(tp: Type): Type = substParams(tp, from, to, this)(using mapCtx)
}

/** An approximating substitution that can handle wildcards in the `to` list */
Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ object TypeOps:
val sym = tp.symbol
if (sym.isStatic && !sym.maybeOwner.seesOpaques || (tp.prefix `eq` NoPrefix)) tp
else derivedSelect(tp, atVariance(variance max 0)(this(tp.prefix)))
case tp: LambdaType =>
mapOverLambda(tp) // special cased common case
case tp: ThisType =>
toPrefix(pre, cls, tp.cls)
case _: BoundType =>
Expand Down Expand Up @@ -136,6 +138,9 @@ object TypeOps:
tp2
case tp1 => tp1
}
case tp: AppliedType =>
val normed = tp.tryNormalize
if normed.exists then normed else tp.map(simplify(_, theMap))
case tp: TypeParamRef =>
val tvar = ctx.typerState.constraint.typeVarOfParam(tp)
if (tvar.exists) tvar else tp
Expand All @@ -147,7 +152,7 @@ object TypeOps:
simplify(l, theMap) & simplify(r, theMap)
case OrType(l, r) if !ctx.mode.is(Mode.Type) =>
simplify(l, theMap) | simplify(r, theMap)
case _: AppliedType | _: MatchType =>
case _: MatchType =>
val normed = tp.tryNormalize
if (normed.exists) normed else mapOver
case tp: MethodicType =>
Expand Down
Loading