Skip to content

Commit ffee8bd

Browse files
committed
Fix handling of singleton types
- Don't widen actual in adaptBoxed if expected is a singleton type - Don't allow singleton types with capture sets (the theory does not allow them either)
1 parent c9f7ee0 commit ffee8bd

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed

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

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ object CheckCaptures:
9494
/** Check that a @retains annotation only mentions references that can be tracked.
9595
* This check is performed at Typer.
9696
*/
97-
def checkWellformed(ann: Tree)(using Context): Unit =
97+
def checkWellformed(parent: Tree, ann: Tree)(using Context): Unit =
98+
parent.tpe match
99+
case _: SingletonType =>
100+
report.error(em"Singleton type $parent cannot have capture set", parent.srcPos)
101+
case _ =>
98102
for elem <- retainedElems(ann) do
99103
elem.tpe match
100104
case ref: CaptureRef =>
@@ -848,21 +852,25 @@ class CheckCaptures extends Recheck, SymTransformer:
848852
adaptedType(boxed)
849853
}
850854

851-
var actualw = actual.widenDealias
852-
actual match
853-
case ref: CaptureRef if ref.isTracked =>
854-
actualw match
855-
case CapturingType(p, refs) if ref.singletonCaptureSet.mightSubcapture(refs) =>
856-
actualw = actualw.derivedCapturingType(p, ref.singletonCaptureSet)
857-
.showing(i"improve $actualw to $result", capt)
858-
// given `a: C T`, improve `C T` to `{a} T`
859-
case _ =>
860-
case _ =>
861-
val adapted = adapt(actualw, expected, covariant = true)
862-
if adapted ne actualw then
863-
capt.println(i"adapt boxed $actual vs $expected ===> $adapted")
864-
adapted
865-
else actual
855+
if expected.isSingleton && actual.isSingleton then
856+
println(i"shot $actual $expected")
857+
actual
858+
else
859+
var actualw = actual.widenDealias
860+
actual match
861+
case ref: CaptureRef if ref.isTracked =>
862+
actualw match
863+
case CapturingType(p, refs) if ref.singletonCaptureSet.mightSubcapture(refs) =>
864+
actualw = actualw.derivedCapturingType(p, ref.singletonCaptureSet)
865+
.showing(i"improve $actualw to $result", capt)
866+
// given `a: T^C`, improve `T^C` to `T^{a}`
867+
case _ =>
868+
case _ =>
869+
val adapted = adapt(actualw, expected, covariant = true)
870+
if adapted ne actualw then
871+
capt.println(i"adapt boxed $actual vs $expected ===> $adapted")
872+
adapted
873+
else actual
866874
end adaptBoxed
867875

868876
/** Check overrides again, taking capture sets into account.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,7 +2897,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28972897
if Feature.ccEnabled
28982898
&& (cls == defn.RetainsAnnot || cls == defn.RetainsByNameAnnot)
28992899
then
2900-
CheckCaptures.checkWellformed(annot1)
2900+
CheckCaptures.checkWellformed(arg1, annot1)
29012901
if arg1.isType then
29022902
assignType(cpy.Annotated(tree)(arg1, annot1), arg1, annot1)
29032903
else
@@ -3957,7 +3957,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
39573957
sym.isConstructor
39583958
|| sym.matchNullaryLoosely
39593959
|| Feature.warnOnMigration(msg, tree.srcPos, version = `3.0`)
3960-
&& {
3960+
&& {
39613961
msg.actions
39623962
.headOption
39633963
.foreach(Rewrites.applyAction)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
val x = () => ()
2+
3+
val y1: x.type = x // ok
4+
val y2: x.type^{} = x // error: singleton type cannot have capture set
5+
val y3: x.type^{x} = x // error: singleton type cannot have capture set // error
6+
val y4: x.type^{cap} = x // error: singleton type cannot have capture set

0 commit comments

Comments
 (0)