Skip to content

Commit 7f63049

Browse files
committed
Switch to AnnotatedType representation of CapturingTypes
1 parent 45c2621 commit 7f63049

File tree

13 files changed

+38
-60
lines changed

13 files changed

+38
-60
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureAnnotation.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,10 @@ case class CaptureAnnotation(refs: CaptureSet) extends Annotation:
5353

5454
override def toText(printer: Printer): Text = refs.toText(printer)
5555

56+
override def hash: Int = refs.hashCode
57+
58+
override def eql(that: Annotation) = that match
59+
case that: CaptureAnnotation => this.refs eq that.refs
60+
case _ => false
61+
5662
end CaptureAnnotation

compiler/src/dotty/tools/dotc/cc/CaptureOps.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ extension (tp: Type)
6464
case TypeBounds(lo, _) => lo.needsBox
6565
case _ => false
6666
case tp: RefinedOrRecType => tp.parent.needsBox
67+
case CapturingType(_, _) => false
6768
case tp: AnnotatedType => tp.parent.needsBox
6869
case tp: LazyRef => tp.ref.needsBox
6970
case tp: AndType => tp.tp1.needsBox || tp.tp2.needsBox

compiler/src/dotty/tools/dotc/cc/CapturingType.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@ import Types.*, Symbols.*, Contexts.*
77

88
object CapturingType:
99

10-
private val old = true
11-
1210
def apply(parent: Type, refs: CaptureSet)(using Context): Type =
13-
if old then CapturingTypeMaker(parent, refs)
14-
else if refs.isAlwaysEmpty then parent
11+
if refs.isAlwaysEmpty then parent
1512
else AnnotatedType(parent, CaptureAnnotation(refs))
1613

1714
def unapply(tp: Type)(using Context) = tp match
18-
case tp: CapturingType => Some((tp.parent, tp.captureSet))
1915
case tp: AnnotatedType => tp.annot match
2016
case ann: CaptureAnnotation =>
2117
Some((tp.parent, ann.refs))

compiler/src/dotty/tools/dotc/core/Annotations.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ object Annotations {
7979

8080
def sameAnnotation(that: Annotation)(using Context): Boolean =
8181
symbol == that.symbol && tree.sameTree(that.tree)
82+
83+
/** Operations for hash-consing, can be overridden */
84+
def hash: Int = System.identityHashCode(this)
85+
def eql(that: Annotation) = this eq that
8286
}
8387

8488
case class ConcreteAnnotation(t: Tree) extends Annotation {

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,7 +1511,7 @@ object SymDenotations {
15111511
case tp: AppliedType => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems)
15121512
case tp: LambdaType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType)
15131513
case tp: AndOrType => hasSkolems(tp.tp1) || hasSkolems(tp.tp2)
1514-
case tp: AnnotOrCaptType => hasSkolems(tp.parent)
1514+
case tp: AnnotatedType => hasSkolems(tp.parent)
15151515
case _ => false
15161516
}
15171517

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
327327
compareWild
328328
case tp2: LazyRef =>
329329
isBottom(tp1) || !tp2.evaluating && recur(tp1, tp2.ref)
330+
case CapturingType(_, _) =>
331+
secondTry
330332
case tp2: AnnotatedType if !tp2.isRefining =>
331333
recur(tp1, tp2.parent)
332334
case tp2: ThisType =>
@@ -741,11 +743,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
741743
false
742744
}
743745
compareTypeBounds
746+
case CapturingType(parent2, _) =>
747+
recur(tp1, parent2) || fourthTry
744748
case tp2: AnnotatedType if tp2.isRefining =>
745749
(tp1.derivesAnnotWith(tp2.annot.sameAnnotation) || tp1.isBottomType) &&
746750
recur(tp1, tp2.parent)
747-
case tp2: CapturingType =>
748-
recur(tp1, tp2.parent) || fourthTry
749751
case ClassInfo(pre2, cls2, _, _, _) =>
750752
def compareClassInfo = tp1 match {
751753
case ClassInfo(pre1, cls1, _, _, _) =>

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ object Types {
7373
* | +- AppliedType
7474
* | +- TypeBounds
7575
* | +- ExprType
76-
* | +- AnnotOrCaptType -+-- AnnotatedType
77-
* | | +-- CapturingType
76+
* | +- AnnotatedType
7877
* | +- TypeVar
7978
* | +- HKTypeLambda
8079
* | +- MatchType
@@ -176,7 +175,6 @@ object Types {
176175
// not on types. Allowing it on types is a Scala 3 extension. See:
177176
// https://www.scala-lang.org/files/archive/spec/2.11/11-annotations.html#scala-compiler-annotations
178177
tp.annot.symbol == defn.UncheckedStableAnnot || tp.parent.isStable
179-
case tp: CapturingType => tp.parent.isStable
180178
case tp: AndType =>
181179
// TODO: fix And type check when tp contains type parames for explicit-nulls flow-typing
182180
// see: tests/explicit-nulls/pos/flow-stable.scala.disabled
@@ -205,6 +203,8 @@ object Types {
205203
else this1.underlying.isRef(sym, skipRefined)
206204
case this1: TypeVar =>
207205
this1.instanceOpt.isRef(sym, skipRefined)
206+
case CapturingType(_, _) =>
207+
false
208208
case this1: AnnotatedType =>
209209
this1.parent.isRef(sym, skipRefined)
210210
case _ => false
@@ -1467,7 +1467,7 @@ object Types {
14671467
case tp: AppliedType =>
14681468
if (tp.tycon.isLambdaSub) NoType
14691469
else tp.superType.underlyingClassRef(refinementOK)
1470-
case tp: AnnotOrCaptType =>
1470+
case tp: AnnotatedType =>
14711471
tp.parent.underlyingClassRef(refinementOK)
14721472
case tp: RefinedType =>
14731473
if (refinementOK) tp.underlying.underlyingClassRef(refinementOK) else NoType
@@ -5142,12 +5142,8 @@ object Types {
51425142

51435143
// ----- Annotated and Import types -----------------------------------------------
51445144

5145-
abstract class AnnotOrCaptType extends CachedProxyType with ValueType:
5146-
def parent: Type
5147-
override def stripped(using Context): Type = parent.stripped
5148-
51495145
/** An annotated type tpe @ annot */
5150-
abstract case class AnnotatedType(parent: Type, annot: Annotation) extends AnnotOrCaptType {
5146+
abstract case class AnnotatedType(parent: Type, annot: Annotation) extends CachedProxyType, ValueType {
51515147

51525148
override def underlying(using Context): Type = parent
51535149

@@ -5160,6 +5156,8 @@ object Types {
51605156

51615157
override def stripAnnots(using Context): Type = parent.stripAnnots
51625158

5159+
override def stripped(using Context): Type = parent.stripped
5160+
51635161
private var isRefiningKnown = false
51645162
private var isRefiningCache: Boolean = _
51655163

@@ -5174,16 +5172,16 @@ object Types {
51745172
// equals comes from case class; no matching override is needed
51755173

51765174
override def computeHash(bs: Binders): Int =
5177-
doHash(bs, System.identityHashCode(annot), parent)
5175+
doHash(bs, annot.hash, parent)
51785176
override def hashIsStable: Boolean =
51795177
parent.hashIsStable
51805178

51815179
override def eql(that: Type): Boolean = that match
5182-
case that: AnnotatedType => (parent eq that.parent) && (annot eq that.annot)
5180+
case that: AnnotatedType => (parent eq that.parent) && (annot eql that.annot)
51835181
case _ => false
51845182

51855183
override def iso(that: Any, bs: BinderPairs): Boolean = that match
5186-
case that: AnnotatedType => parent.equals(that.parent, bs) && (annot eq that.annot)
5184+
case that: AnnotatedType => parent.equals(that.parent, bs) && (annot eql that.annot)
51875185
case _ => false
51885186
}
51895187

@@ -5196,37 +5194,6 @@ object Types {
51965194
unique(CachedAnnotatedType(parent, annot))
51975195
end AnnotatedType
51985196

5199-
abstract class CapturingType(val parent: Type, private val refs: CaptureSet) extends AnnotOrCaptType:
5200-
override def underlying(using Context): Type = parent
5201-
5202-
override def captureSet(using Context) = refs
5203-
5204-
def derivedCapturingType(parent: Type, refs: CaptureSet)(using Context): Type =
5205-
if (parent eq this.parent) && (refs eq this.refs) then this
5206-
else CapturingType(parent, refs)
5207-
5208-
// equals comes from case class; no matching override is needed
5209-
5210-
override def computeHash(bs: Binders): Int =
5211-
doHash(bs, refs, parent)
5212-
override def hashIsStable: Boolean =
5213-
parent.hashIsStable
5214-
5215-
override def eql(that: Type): Boolean = that match
5216-
case that: CapturingType => (parent eq that.parent) && (refs eq that.refs)
5217-
case _ => false
5218-
5219-
override def iso(that: Any, bs: BinderPairs): Boolean = that match
5220-
case that: CapturingType => parent.equals(that.parent, bs) && (refs eq that.refs)
5221-
case _ => false
5222-
5223-
class CachedCapturingType(parent: Type, refs: CaptureSet) extends CapturingType(parent, refs)
5224-
5225-
object CapturingTypeMaker:
5226-
def apply(parent: Type, refs: CaptureSet)(using Context): Type =
5227-
if refs.isAlwaysEmpty then parent
5228-
else unique(CachedCapturingType(parent, refs))
5229-
52305197
// Special type objects and classes -----------------------------------------------------
52315198

52325199
/** The type of an erased array */
@@ -5363,7 +5330,7 @@ object Types {
53635330
zeroParamClass(tp.underlying)
53645331
case tp: TypeVar =>
53655332
zeroParamClass(tp.underlying)
5366-
case tp: AnnotOrCaptType =>
5333+
case tp: AnnotatedType =>
53675334
zeroParamClass(tp.underlying)
53685335
case _ =>
53695336
NoType

compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ object GenericSignatures {
347347
if (toplevel) polyParamSig(tParams)
348348
superSig(ci.typeSymbol, ci.parents)
349349

350-
case tp: AnnotOrCaptType =>
350+
case tp: AnnotatedType =>
351351
jsig(tp.parent, toplevel, primitiveOK)
352352

353353
case hktl: HKTypeLambda =>
@@ -469,7 +469,7 @@ object GenericSignatures {
469469
true
470470
case ClassInfo(_, _, parents, _, _) =>
471471
foldOver(tp.typeParams.nonEmpty, parents)
472-
case tp: AnnotOrCaptType =>
472+
case tp: AnnotatedType =>
473473
foldOver(x, tp.parent)
474474
case _ =>
475475
foldOver(x, tp)

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ object TypeTestsCasts {
148148
}
149149
case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
150150
case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
151-
case tp: AnnotOrCaptType => recur(X, tp.parent)
151+
case tp: AnnotatedType => recur(X, tp.parent)
152152
case _: RefinedType => false
153153
case _ => true
154154
})

compiler/src/dotty/tools/dotc/typer/CheckCaptures.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ class CheckCaptures extends Recheck:
108108

109109
val mapType = new TypeMap:
110110
def apply(t: Type) = t match
111-
case AnnotatedType(parent, annot) if annot.symbol == defn.RetainsAnnot =>
111+
case AnnotatedType(parent, annot)
112+
if annot.symbol == defn.RetainsAnnot && !annot.isInstanceOf[CaptureAnnotation] =>
112113
CapturingType(this(parent), annot.tree.toCaptureSet)
113114
case t @ RefinedType(core, nme.apply, appInfo) =>
114115
mapRefined(t, this(core), this(appInfo))
@@ -118,7 +119,8 @@ class CheckCaptures extends Recheck:
118119
def reinfer(tp: Type): Type =
119120
val cleanType = new TypeMap:
120121
def apply(t: Type) = t match
121-
case AnnotatedType(parent, annot) if annot.symbol == defn.RetainsAnnot =>
122+
case AnnotatedType(parent, annot)
123+
if annot.symbol == defn.RetainsAnnot =>
122124
parent
123125
case _ =>
124126
mapOver(t)

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ object Checking {
309309
case AndType(tp1, tp2) => isInteresting(tp1) || isInteresting(tp2)
310310
case OrType(tp1, tp2) => isInteresting(tp1) && isInteresting(tp2)
311311
case _: RefinedOrRecType | _: AppliedType => true
312-
case tp: AnnotOrCaptType => isInteresting(tp.parent)
312+
case tp: AnnotatedType => isInteresting(tp.parent)
313313
case _ => false
314314
}
315315

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ object Inferencing {
127127
couldInstantiateTypeVar(parent)
128128
case tp: AndOrType =>
129129
couldInstantiateTypeVar(tp.tp1) || couldInstantiateTypeVar(tp.tp2)
130-
case tp: AnnotOrCaptType =>
130+
case tp: AnnotatedType =>
131131
couldInstantiateTypeVar(tp.parent)
132132
case _ =>
133133
false

tests/neg-custom-args/captures/capt-depfun2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ def f(y: Cap, z: Cap) =
55
def g(): C @retains(y, z) = ???
66
val ac: ((x: Cap) => Array[String @retains(x)]) = ???
77
val dc = ac(g()) // error: Needs explicit type Array[? >: String <: {y, z} String]
8-
// This is a shotcoming of rechecking since the originally inferred
8+
// This is a shortcoming of rechecking since the originally inferred
99
// type is `Array[String]` and the actual type after rechecking
1010
// cannot be expressed as `Array[C String]` for any capture set C

0 commit comments

Comments
 (0)