Skip to content

Commit

Permalink
Make capture parameters and members bounded by CapSet by default
Browse files Browse the repository at this point in the history
  • Loading branch information
noti0na1 committed Nov 21, 2024
1 parent 5d1d274 commit 3e443b6
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 6 deletions.
10 changes: 7 additions & 3 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -527,10 +527,14 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def makeCapsOf(tp: RefTree)(using Context): Tree =
TypeApply(Select(scalaDot(nme.caps), nme.capsOf), tp :: Nil)

def makeCapsBound()(using Context): Tree =
makeRetaining(
// `type C^` and `[C^]` becomes:
// `type C >: CapSet <: CapSet^{cap}` and `[C >: CapSet <: CapSet^{cap}]`
def makeCapsBound()(using Context): TypeBoundsTree =
TypeBoundsTree(
Select(scalaDot(nme.caps), tpnme.CapSet),
Nil, tpnme.retainsCap)
makeRetaining(
Select(scalaDot(nme.caps), tpnme.CapSet),
Nil, tpnme.retainsCap))

def makeConstructor(tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(using Context): DefDef =
DefDef(nme.CONSTRUCTOR, joinParams(tparams, vparamss), TypeTree(), rhs)
Expand Down
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2240,7 +2240,7 @@ object Parsers {
atSpan(in.offset):
if in.isIdent(nme.UPARROW) && Feature.ccEnabled then
in.nextToken()
TypeBoundsTree(EmptyTree, makeCapsBound())
makeCapsBound()
else
TypeBoundsTree(bound(SUPERTYPE), bound(SUBTYPE))

Expand Down Expand Up @@ -4057,8 +4057,11 @@ object Parsers {
|| sourceVersion.isAtLeast(`3.6`) && in.isColon =>
makeTypeDef(typeAndCtxBounds(tname))
case _ =>
syntaxErrorOrIncomplete(ExpectedTypeBoundOrEquals(in.token))
return EmptyTree // return to avoid setting the span to EmptyTree
if in.isIdent(nme.UPARROW) && Feature.ccEnabled then
makeTypeDef(typeAndCtxBounds(tname))
else
syntaxErrorOrIncomplete(ExpectedTypeBoundOrEquals(in.token))
return EmptyTree // return to avoid setting the span to EmptyTree
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions tests/neg-custom-args/captures/capset-bound2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import caps.*

class IO

def f[C^](io: IO^{C^}) = ???

def test =
f[CapSet](???)
f[CapSet^{}](???)
f[CapSet^](???)
f[Nothing](???) // error
f[String](???) // error

21 changes: 21 additions & 0 deletions tests/neg-custom-args/captures/capset-members.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import caps.*

trait Abstract[X^]:
type C >: X <: CapSet^
def boom(): Unit^{C^}

class Concrete extends Abstract[CapSet^{}]:
type C = CapSet^{}
def boom() = ()

class Concrete2 extends Abstract[CapSet^{}]:
type C = CapSet^{} & CapSet^{}
def boom() = ()

class Concrete3 extends Abstract[CapSet^{}]:
type C = CapSet^{} | CapSet^{}
def boom() = ()

class Concrete4 extends Abstract[CapSet^{}]:
type C = Nothing // error
def boom() = ()

0 comments on commit 3e443b6

Please sign in to comment.