Skip to content

Cache AnnotatedTypes #9743

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 2 commits into from
Sep 8, 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
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Hashable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ trait Hashable {
protected final def doHash(bs: Binders, x1: Any, tp2: Type): Int =
finishHash(bs, hashing.mix(hashSeed, x1.hashCode), 1, tp2)

protected final def doHash(bs: Binders, x1: Int, tp2: Type): Int =
finishHash(bs, hashing.mix(hashSeed, x1), 1, tp2)

protected final def doHash(bs: Binders, tp1: Type, tp2: Type): Int =
finishHash(bs, hashSeed, 0, tp1, tp2)

Expand Down
32 changes: 21 additions & 11 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ object Types {
final def exists: Boolean = this.ne(NoType)

/** This type, if it exists, otherwise `that` type */
inline def orElse(inline that: => Type): Type = if (exists) this else that
inline def orElse(inline that: Type): Type = if (exists) this else that

/** Is this type a value type? */
final def isValueType: Boolean = this.isInstanceOf[ValueType]
Expand Down Expand Up @@ -4672,12 +4672,11 @@ object Types {
// ----- Annotated and Import types -----------------------------------------------

/** An annotated type tpe @ annot */
case class AnnotatedType(parent: Type, annot: Annotation) extends UncachedProxyType with ValueType {
// todo: cache them? but this makes only sense if annotations and trees are also cached.
abstract case class AnnotatedType(parent: Type, annot: Annotation) extends CachedProxyType with ValueType {

override def underlying(using Context): Type = parent

def derivedAnnotatedType(parent: Type, annot: Annotation): AnnotatedType =
def derivedAnnotatedType(parent: Type, annot: Annotation)(using Context): AnnotatedType =
if ((parent eq this.parent) && (annot eq this.annot)) this
else AnnotatedType(parent, annot)

Expand All @@ -4699,17 +4698,28 @@ object Types {

// equals comes from case class; no matching override is needed

override def iso(that: Any, bs: BinderPairs): Boolean = that match {
case that: AnnotatedType => parent.equals(that.parent, bs) && (annot `eq` that.annot)
override def computeHash(bs: Binders): Int =
doHash(bs, System.identityHashCode(annot), parent)
override def hashIsStable: Boolean =
parent.hashIsStable

override def eql(that: Type): Boolean = that match
case that: AnnotatedType => (parent eq that.parent) && (annot eq that.annot)
case _ => false
}
}

object AnnotatedType {
def make(underlying: Type, annots: List[Annotation]): Type =
annots.foldLeft(underlying)(AnnotatedType(_, _))
override def iso(that: Any, bs: BinderPairs): Boolean = that match
case that: AnnotatedType => parent.equals(that.parent, bs) && (annot eq that.annot)
case _ => false
}

class CachedAnnotatedType(parent: Type, annot: Annotation) extends AnnotatedType(parent, annot)

object AnnotatedType:
def make(underlying: Type, annots: List[Annotation])(using Context): Type =
annots.foldLeft(underlying)(apply(_, _))
def apply(parent: Type, annot: Annotation)(using Context): AnnotatedType =
unique(CachedAnnotatedType(parent, annot))

// Special type objects and classes -----------------------------------------------------

/** The type of an erased array */
Expand Down