Skip to content

Commit cb24fa9

Browse files
noti0na1bracevac
authored andcommitted
Remove unnecessary ^ in capture set syntax.
1 parent fa34018 commit cb24fa9

32 files changed

+117
-103
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,16 @@ object Mode {
9191
*/
9292
val ImplicitExploration: Mode = newMode(12, "ImplicitExploration")
9393

94+
/** We are currently inside a capture set.
95+
* A term name could be a capture variable, so we need to
96+
* check that it is valid to use as type name.
97+
* Since this mode is only used during annotation typing,
98+
* we can reuse the value of `ImplicitExploration` to save bits.
99+
*/
100+
val InCaptureSet: Mode = newMode(13, "InCaptureSet")
101+
94102
/** We are currently unpickling Scala2 info */
95-
val Scala2Unpickling: Mode = newMode(13, "Scala2Unpickling")
103+
val Scala2Unpickling: Mode = newMode(14, "Scala2Unpickling")
96104

97105
/** Signifies one of two possible situations:
98106
* 1. We are currently checking bounds to be non-empty, so we should not

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,8 +1600,8 @@ object Parsers {
16001600
case _ => None
16011601
}
16021602

1603-
/** CaptureRef ::= { SimpleRef `.` } SimpleRef [`*`] [`.` rd]
1604-
* | [ { SimpleRef `.` } SimpleRef `.` ] id `^`
1603+
/** CaptureRef ::= { SimpleRef `.` } SimpleRef [`*`]
1604+
* | [ { SimpleRef `.` } SimpleRef `.` ] id
16051605
*/
16061606
def captureRef(): Tree =
16071607

@@ -1620,12 +1620,6 @@ object Parsers {
16201620
in.nextToken()
16211621
derived(reachRef, nme.CC_READONLY)
16221622
else reachRef
1623-
else if isIdent(nme.UPARROW) then
1624-
in.nextToken()
1625-
atSpan(startOffset(ref)):
1626-
convertToTypeId(ref) match
1627-
case ref: RefTree => makeCapsOf(ref)
1628-
case ref => ref
16291623
else ref
16301624

16311625
recur(simpleRef())

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import annotation.threadUnsafe
3636

3737
import scala.util.control.NonFatal
3838
import dotty.tools.dotc.inlines.Inlines
39+
import dotty.tools.dotc.cc.isRetains
3940

4041
object Applications {
4142
import tpd.*
@@ -1115,7 +1116,9 @@ trait Applications extends Compatibility {
11151116
val fun2 = Applications.retypeSignaturePolymorphicFn(fun1, methType)
11161117
simpleApply(fun2, proto)
11171118
case funRef: TermRef =>
1118-
val app = ApplyTo(tree, fun1, funRef, proto, pt)
1119+
// println(i"typedApply: $funRef, ${tree.args}, ${funRef.symbol.maybeOwner.isRetains}")
1120+
val applyCtx = if funRef.symbol.maybeOwner.isRetains then ctx.addMode(Mode.InCaptureSet) else ctx
1121+
val app = ApplyTo(tree, fun1, funRef, proto, pt)(using applyCtx)
11191122
convertNewGenericArray(
11201123
widenEnumCase(
11211124
postProcessByNameArgs(funRef, app).computeNullable(),

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
715715
&& ctx.owner.owner.unforcedDecls.lookup(tree.name).exists
716716
then // we are in the arguments of a this(...) constructor call
717717
errorTree(tree, em"$tree is not accessible from constructor arguments")
718+
else if ctx.mode.is(Mode.InCaptureSet) then
719+
// If we are in a capture set and the identifier is not a term name,
720+
// try to type it with the same name but as a type
721+
typed(untpd.makeCapsOf(untpd.cpy.Ident(tree)(name.toTypeName)), pt)
718722
else
719723
errorTree(tree, MissingIdent(tree, kind, name, pt))
720724
end typedIdent
@@ -920,6 +924,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
920924
typedCBSelect(tree0, pt, qual)
921925
else EmptyTree
922926

927+
// Otherwise, if we are in a capture set, try to type it as a capture variable
928+
// reference (as selecting a type name).
929+
def trySelectTypeInCaptureSet() =
930+
if ctx.mode.is(Mode.InCaptureSet) && tree0.name.isTypeName then
931+
typedSelectWithAdapt(untpd.cpy.Select(tree0)(qual, tree0.name.toTypeName), pt, qual)
932+
else EmptyTree
933+
923934
// Otherwise, report an error
924935
def reportAnError() =
925936
assignType(tree,
@@ -941,6 +952,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
941952
.orElse(tryDynamic())
942953
.orElse(trySelectable())
943954
.orElse(tryCBCompanion())
955+
.orElse(trySelectTypeInCaptureSet())
944956
.orElse(reportAnError())
945957
end typedSelectWithAdapt
946958

tests/neg-custom-args/captures/capset-bound.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class IO
55
case class File(io: IO^)
66

77
def test(io1: IO^, io2: IO^) =
8-
def f[C >: CapSet^{io1} <: CapSet^](file: File^{C^}) = ???
8+
def f[C >: CapSet^{io1} <: CapSet^](file: File^{C}) = ???
99
val f1: File^{io1} = ???
1010
val f2: File^{io2} = ???
1111
val f3: File^{io1, io2} = ???

tests/neg-custom-args/captures/capset-bound2.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import caps.*
22

33
class IO
44

5-
def f[C^](io: IO^{C^}) = ???
5+
def f[C^](io: IO^{C}) = ???
66

77
def test =
88
f[CapSet](???)
99
f[CapSet^{}](???)
1010
f[CapSet^](???)
1111
f[Nothing](???) // error
1212
f[String](???) // error
13-

tests/neg-custom-args/captures/capset-members.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import caps.*
33
trait Abstract[X^]:
44
type C >: X <: CapSet^
55
// Don't test the return type using Unit, because it is a pure type.
6-
def boom(): AnyRef^{C^}
6+
def boom(): AnyRef^{C}
77

88
class Concrete extends Abstract[CapSet^{}]:
99
type C = CapSet^{}
@@ -27,4 +27,3 @@ class Concrete5(a: AnyRef^, b: AnyRef^) extends Abstract[CapSet^{a}]:
2727

2828
class Concrete6(a: AnyRef^, b: AnyRef^) extends Abstract[CapSet^{a}]:
2929
def boom(): AnyRef^{b} = b // error
30-

tests/neg-custom-args/captures/capture-parameters.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import caps.*
22

33
class C
44

5-
def test[X^, Y^, Z >: X <: Y](x: C^{X^}, y: C^{Y^}, z: C^{Z^}) =
6-
val x2z: C^{Z^} = x
7-
val z2y: C^{Y^} = z
8-
val x2y: C^{Y^} = x // error
9-
5+
def test[X^, Y^, Z >: X <: Y](x: C^{X}, y: C^{Y}, z: C^{Z}) =
6+
val x2z: C^{Z} = x
7+
val z2y: C^{Y} = z
8+
val x2y: C^{Y} = x // error

tests/neg-custom-args/captures/capture-poly.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ trait Foo extends Capability
55
trait CaptureSet:
66
type C >: CapSet <: CapSet^
77

8-
def capturePoly[C^](a: Foo^{C^}): Foo^{C^} = a
9-
def capturePoly2(c: CaptureSet)(a: Foo^{c.C^}): Foo^{c.C^} = a
8+
def capturePoly[C^](a: Foo^{C}): Foo^{C} = a
9+
def capturePoly2(c: CaptureSet)(a: Foo^{c.C}): Foo^{c.C} = a
1010

1111
def test =
1212
val x: Foo^ = ???
@@ -15,8 +15,8 @@ def test =
1515
object X extends CaptureSet:
1616
type C = CapSet^{x}
1717

18-
val z1: Foo^{X.C^} = x
19-
val z2: Foo^{X.C^} = y // error
18+
val z1: Foo^{X.C} = x
19+
val z2: Foo^{X.C} = y // error
2020

2121
val z3: Foo^{x} = capturePoly(x)
2222
val z4: Foo^{x} = capturePoly(y) // error

tests/neg-custom-args/captures/capture-vars-subtyping.scala

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,32 @@ import caps.*
33

44
def test[C^] =
55
val a: C = ???
6-
val b: CapSet^{C^} = a
6+
val b: CapSet^{C} = a
77
val c: C = b
8-
val d: CapSet^{C^, c} = a
8+
val d: CapSet^{C, c} = a
99

1010
// TODO: make "CapSet-ness" of type variables somehow contagious?
1111
// Then we don't have to spell out the bounds explicitly...
1212
def testTrans[C^, D >: CapSet <: C, E >: CapSet <: D, F >: C <: CapSet^] =
1313
val d1: D = ???
14-
val d2: CapSet^{D^} = d1
14+
val d2: CapSet^{D} = d1
1515
val d3: D = d2
1616
val e1: E = ???
17-
val e2: CapSet^{E^} = e1
17+
val e2: CapSet^{E} = e1
1818
val e3: E = e2
1919
val d4: D = e1
2020
val c1: C = d1
2121
val c2: C = e1
2222
val f1: F = c1
23-
val d_e_f1: CapSet^{D^,E^,F^} = d1
24-
val d_e_f2: CapSet^{D^,E^,F^} = e1
25-
val d_e_f3: CapSet^{D^,E^,F^} = f1
23+
val d_e_f1: CapSet^{D,E,F} = d1
24+
val d_e_f2: CapSet^{D,E,F} = e1
25+
val d_e_f3: CapSet^{D,E,F} = f1
2626
val f2: F = d_e_f1
2727
val c3: C = d_e_f1 // error
2828
val c4: C = f1 // error
2929
val e4: E = f1 // error
3030
val e5: E = d1 // error
31-
val c5: CapSet^{C^} = e1
31+
val c5: CapSet^{C} = e1
3232

3333

3434
trait A[+T]
@@ -37,12 +37,12 @@ trait B[-C]
3737

3838
def testCong[C^, D^] =
3939
val a: A[C] = ???
40-
val b: A[CapSet^{C^}] = a
41-
val c: A[CapSet^{D^}] = a // error
42-
val d: A[CapSet^{C^,D^}] = a
40+
val b: A[CapSet^{C}] = a
41+
val c: A[CapSet^{D}] = a // error
42+
val d: A[CapSet^{C,D}] = a
4343
val e: A[C] = d // error
4444
val f: B[C] = ???
45-
val g: B[CapSet^{C^}] = f
45+
val g: B[CapSet^{C}] = f
4646
val h: B[C] = g
47-
val i: B[CapSet^{C^,D^}] = h // error
47+
val i: B[CapSet^{C,D}] = h // error
4848
val j: B[C] = i

0 commit comments

Comments
 (0)