diff --git a/compiler/src/dotty/tools/dotc/core/Hashable.scala b/compiler/src/dotty/tools/dotc/core/Hashable.scala index 7a419efa1a9a..c8058daf8c66 100644 --- a/compiler/src/dotty/tools/dotc/core/Hashable.scala +++ b/compiler/src/dotty/tools/dotc/core/Hashable.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5856e8acbca0..8c3883cfd2f6 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -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] @@ -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) @@ -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 */