Skip to content

Fix #3250: Make HKLambda a cached type #3287

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 3 commits into from
Oct 9, 2017
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
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Constraint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package dotc
package core

import Types._, Contexts._, Symbols._
import util.SimpleMap
import collection.mutable
import printing.{Printer, Showable}
import printing.Texts._
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Comments._
import util.Positions._
import ast.Trees._
import ast.untpd
import util.{FreshNameCreator, SimpleMap, SourceFile, NoSource}
import util.{FreshNameCreator, SimpleIdentityMap, SourceFile, NoSource}
import typer.{Implicits, ImplicitRunInfo, ImportInfo, Inliner, NamerContextOps, SearchHistory, TypeAssigner, Typer}
import Implicits.ContextualImplicits
import config.Settings._
Expand Down Expand Up @@ -694,14 +694,14 @@ object Contexts {
implicit val ctx: Context = initctx
}

class GADTMap(initBounds: SimpleMap[Symbol, TypeBounds]) extends util.DotClass {
class GADTMap(initBounds: SimpleIdentityMap[Symbol, TypeBounds]) extends util.DotClass {
private var myBounds = initBounds
def setBounds(sym: Symbol, b: TypeBounds): Unit =
myBounds = myBounds.updated(sym, b)
def bounds = myBounds
}

@sharable object EmptyGADTMap extends GADTMap(SimpleMap.Empty) {
@sharable object EmptyGADTMap extends GADTMap(SimpleIdentityMap.Empty) {
override def setBounds(sym: Symbol, b: TypeBounds) = unsupported("EmptyGADTMap.setBounds")
}
}
19 changes: 8 additions & 11 deletions compiler/src/dotty/tools/dotc/core/Names.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ import StdNames.str
import Designators._
import util.Chars.isIdentifierStart
import collection.IndexedSeqOptimized
import collection.generic.CanBuildFrom
import collection.mutable.{ Builder, StringBuilder, AnyRefMap }
import collection.immutable.WrappedString
import collection.generic.CanBuildFrom
import util.{DotClass, SimpleMap}
import collection.immutable
import util.{DotClass}
import config.Config
import java.util.HashMap

Expand Down Expand Up @@ -193,24 +190,24 @@ object Names {
def underlying: TermName = unsupported("underlying")

@sharable // because of synchronized block in `and`
private var derivedNames: AnyRef /* SimpleMap | j.u.HashMap */ =
SimpleMap.Empty[NameInfo]
private var derivedNames: AnyRef /* immutable.Map[NameInfo, DerivedName] | j.u.HashMap */ =
immutable.Map.empty[NameInfo, DerivedName]

private def getDerived(info: NameInfo): DerivedName /* | Null */= derivedNames match {
case derivedNames: SimpleMap[NameInfo, DerivedName] @unchecked =>
derivedNames(info)
case derivedNames: immutable.AbstractMap[NameInfo, DerivedName] @unchecked =>
if (derivedNames.contains(info)) derivedNames(info) else null
case derivedNames: HashMap[NameInfo, DerivedName] @unchecked =>
derivedNames.get(info)
}

private def putDerived(info: NameInfo, name: DerivedName): name.type = {
derivedNames match {
case derivedNames: SimpleMap[NameInfo, DerivedName] @unchecked =>
case derivedNames: immutable.Map[NameInfo, DerivedName] @unchecked =>
if (derivedNames.size < 4)
this.derivedNames = derivedNames.updated(info, name)
else {
val newMap = new HashMap[NameInfo, DerivedName]
derivedNames.foreachBinding(newMap.put(_, _))
derivedNames.foreach { case (k, v) => newMap.put(k, v) }
newMap.put(info, name)
this.derivedNames = newMap
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dotc
package core

import Types._, Contexts._, Symbols._, Decorators._
import util.SimpleMap
import util.SimpleIdentityMap
import collection.mutable
import printing.{Printer, Showable}
import printing.Texts._
Expand All @@ -14,7 +14,7 @@ import annotation.tailrec

object OrderingConstraint {

type ArrayValuedMap[T] = SimpleMap[TypeLambda, Array[T]]
type ArrayValuedMap[T] = SimpleIdentityMap[TypeLambda, Array[T]]

/** The type of `OrderingConstraint#boundsMap` */
type ParamBounds = ArrayValuedMap[Type]
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Decorators.SymbolIteratorDecorator
import ast._
import annotation.tailrec
import CheckRealizable._
import util.SimpleMap
import util.SimpleIdentityMap
import util.Stats
import java.util.WeakHashMap
import config.Config
Expand Down Expand Up @@ -1254,7 +1254,7 @@ object SymDenotations {
// ----- caches -------------------------------------------------------

private[this] var myTypeParams: List[TypeSymbol] = null
private[this] var fullNameCache: SimpleMap[QualifiedNameKind, Name] = SimpleMap.Empty
private[this] var fullNameCache: SimpleIdentityMap[QualifiedNameKind, Name] = SimpleIdentityMap.Empty

private[this] var myMemberCache: LRUCache[Name, PreDenotation] = null
private[this] var myMemberCachePeriod: Period = Nowhere
Expand Down Expand Up @@ -2041,7 +2041,7 @@ object SymDenotations {
}

private class MemberNamesImpl(createdAt: Period) extends InheritedCacheImpl(createdAt) with MemberNames {
private[this] var cache: SimpleMap[NameFilter, Set[Name]] = SimpleMap.Empty
private[this] var cache: SimpleIdentityMap[NameFilter, Set[Name]] = SimpleIdentityMap.Empty

final def isValid(implicit ctx: Context): Boolean =
cache != null && isValidAt(ctx.phase)
Expand All @@ -2054,7 +2054,7 @@ object SymDenotations {
*/
def invalidate(): Unit =
if (cache != null)
if (locked) cache = SimpleMap.Empty
if (locked) cache = SimpleIdentityMap.Empty
else {
cache = null
invalidateDependents()
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Types._, Contexts._, Symbols._, Flags._, Names._, NameOps._, Denotations.
import Decorators._
import StdNames.{nme, tpnme}
import collection.mutable
import util.{Stats, DotClass, SimpleMap}
import util.{Stats, DotClass}
import config.Config
import config.Printers.{typr, constr, subtyping, noPrinter}
import TypeErasure.{erasedLub, erasedGlb}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import StdNames._
import Annotations._
import annotation.tailrec
import config.Config
import util.{SimpleMap, Property}
import util.Property
import collection.mutable
import ast.tpd._

Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TyperState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package core
import Types._
import Flags._
import Contexts._
import util.{SimpleMap, DotClass}
import util.{SimpleIdentityMap, DotClass}
import reporting._
import printing.{Showable, Printer}
import printing.Texts._
Expand All @@ -24,7 +24,7 @@ class TyperState(previous: TyperState /* | Null */) extends DotClass with Showab
def setReporter(reporter: Reporter): this.type = { myReporter = reporter; this }

private var myConstraint: Constraint =
if (previous == null) new OrderingConstraint(SimpleMap.Empty, SimpleMap.Empty, SimpleMap.Empty)
if (previous == null) new OrderingConstraint(SimpleIdentityMap.Empty, SimpleIdentityMap.Empty, SimpleIdentityMap.Empty)
else previous.constraint

def constraint = myConstraint
Expand Down
33 changes: 28 additions & 5 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Periods._
import Designators._
import util.Positions.{Position, NoPosition}
import util.Stats._
import util.{DotClass, SimpleMap}
import util.DotClass
import reporting.diagnostic.Message
import reporting.diagnostic.messages.CyclicReferenceInvolving
import ast.tpd._
Expand Down Expand Up @@ -2599,7 +2599,32 @@ object Types {
final override def toString = s"$prefixString($paramNames, $paramInfos, $resType)"
}

trait HKLambda extends LambdaType
abstract class HKLambda extends CachedProxyType with LambdaType {
final override def underlying(implicit ctx: Context) = resType

final override def computeHash = doHash(paramNames, resType, paramInfos)

final override def equals(that: Any) = that match {
case that: HKLambda =>
paramNames == that.paramNames &&
paramInfos == that.paramInfos &&
resType == that.resType &&
companion.eq(that.companion)
case _ =>
false
}

final override def eql(that: Type) = that match {
case that: HKLambda =>
paramNames.equals(that.paramNames) &&
paramInfos.equals(that.paramInfos) &&
resType.equals(that.resType) &&
Copy link
Member

Choose a reason for hiding this comment

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

That was already the case before #3239, but why is this equals and not eq?

Copy link
Contributor Author

@odersky odersky Oct 9, 2017

Choose a reason for hiding this comment

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

I am not even sure that equals is needed. But the idea is that, since many types get a compiler generated equals since they are case classes, the rest of the types would conform to that.

companion.eq(that.companion)
case _ =>
false
}
}

trait MethodOrPoly extends LambdaType with MethodicType

trait TermLambda extends LambdaType { thisLambdaType =>
Expand Down Expand Up @@ -2909,7 +2934,7 @@ object Types {
*/
class HKTypeLambda(val paramNames: List[TypeName])(
paramInfosExp: HKTypeLambda => List[TypeBounds], resultTypeExp: HKTypeLambda => Type)
extends UncachedProxyType with HKLambda with TypeLambda {
extends HKLambda with TypeLambda {
type This = HKTypeLambda
def companion = HKTypeLambda

Expand All @@ -2919,8 +2944,6 @@ object Types {
assert(resType.isInstanceOf[TermType], this)
assert(paramNames.nonEmpty)

final override def underlying(implicit ctx: Context) = resType

protected def prefixString = "HKTypeLambda"
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import ErrorReporting.errorTree

import annotation.unchecked
import util.Positions._
import util.{SimpleMap, Stats}
import util.Stats
import util.common._
import transform.SymUtils._
import Decorators._
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/ImportInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ast.{tpd, untpd}
import ast.Trees._
import core._
import printing.{Printer, Showable}
import util.SimpleMap
import util.SimpleIdentityMap
import Symbols._, Names._, Denotations._, Types._, Contexts._, StdNames._, Flags._
import Decorators.StringInterpolators

Expand Down Expand Up @@ -52,7 +52,7 @@ class ImportInfo(symf: Context => Symbol, val selectors: List[untpd.Tree],
def excluded: Set[TermName] = { ensureInitialized(); myExcluded }

/** A mapping from renamed to original names */
def reverseMapping: SimpleMap[TermName, TermName] = { ensureInitialized(); myMapped }
def reverseMapping: SimpleIdentityMap[TermName, TermName] = { ensureInitialized(); myMapped }

/** The original names imported by-name before renaming */
def originals: Set[TermName] = { ensureInitialized(); myOriginals }
Expand All @@ -61,14 +61,14 @@ class ImportInfo(symf: Context => Symbol, val selectors: List[untpd.Tree],
def isWildcardImport = { ensureInitialized(); myWildcardImport }

private var myExcluded: Set[TermName] = null
private var myMapped: SimpleMap[TermName, TermName] = null
private var myMapped: SimpleIdentityMap[TermName, TermName] = null
private var myOriginals: Set[TermName] = null
private var myWildcardImport: Boolean = false

/** Compute info relating to the selector list */
private def ensureInitialized(): Unit = if (myExcluded == null) {
myExcluded = Set()
myMapped = SimpleMap.Empty
myMapped = SimpleIdentityMap.Empty
myOriginals = Set()
def recur(sels: List[untpd.Tree]): Unit = sels match {
case sel :: sels1 =>
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Inferencing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Scopes._
import ProtoTypes._
import annotation.unchecked
import util.Positions._
import util.{Stats, SimpleMap}
import util.{Stats, SimpleIdentityMap}
import util.common._
import Decorators._
import Uniques._
Expand Down Expand Up @@ -286,7 +286,7 @@ object Inferencing {
result
}

type VarianceMap = SimpleMap[TypeVar, Integer]
type VarianceMap = SimpleIdentityMap[TypeVar, Integer]

/** All occurrences of type vars in this type that satisfy predicate
* `include` mapped to their variances (-1/0/1) in this type, where
Expand Down Expand Up @@ -350,7 +350,7 @@ object Inferencing {
if (vmap1 eq vmap) vmap else propagate(vmap1)
}

propagate(accu(SimpleMap.Empty, tp))
propagate(accu(SimpleIdentityMap.Empty, tp))
}
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Constants._
import Scopes._
import annotation.unchecked
import util.Positions._
import util.{Stats, SimpleMap}
import util.{Stats, SimpleIdentityMap}
import util.common._
import Decorators._
import Uniques._
Expand Down Expand Up @@ -179,10 +179,10 @@ object ProtoTypes {
override def resultType(implicit ctx: Context) = resType

/** A map in which typed arguments can be stored to be later integrated in `typedArgs`. */
private var myTypedArg: SimpleMap[untpd.Tree, Tree] = SimpleMap.Empty
private var myTypedArg: SimpleIdentityMap[untpd.Tree, Tree] = SimpleIdentityMap.Empty

/** A map recording the typer states in which arguments stored in myTypedArg were typed */
private var evalState: SimpleMap[untpd.Tree, TyperState] = SimpleMap.Empty
private var evalState: SimpleIdentityMap[untpd.Tree, TyperState] = SimpleIdentityMap.Empty

def isMatchedBy(tp: Type)(implicit ctx: Context) =
typer.isApplicable(tp, Nil, typedArgs, resultType)
Expand Down
Loading