Skip to content

Commit

Permalink
Allow @retains arguments to be context functions (#20232)
Browse files Browse the repository at this point in the history
Suppress the creation of apply method selections for these arguments

Fixes #20231
  • Loading branch information
odersky authored Apr 18, 2024
2 parents fe3f8ef + 829e84a commit 75f38b5
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 3 deletions.
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@ class Definitions {
@tu lazy val RetainsAnnot: ClassSymbol = requiredClass("scala.annotation.retains")
@tu lazy val RetainsCapAnnot: ClassSymbol = requiredClass("scala.annotation.retainsCap")
@tu lazy val RetainsByNameAnnot: ClassSymbol = requiredClass("scala.annotation.retainsByName")
@tu lazy val RetainsArgAnnot: ClassSymbol = requiredClass("scala.annotation.retainsArg")
@tu lazy val PublicInBinaryAnnot: ClassSymbol = requiredClass("scala.annotation.publicInBinary")

@tu lazy val JavaRepeatableAnnot: ClassSymbol = requiredClass("java.lang.annotation.Repeatable")
Expand Down
5 changes: 5 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4047,10 +4047,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
true
}

def isRetainsArg(pt: Type) = pt match
case AnnotatedType(arg, annot) => annot.symbol == defn.RetainsArgAnnot
case _ => false

if (implicitFun || caseCompanion)
&& !isApplyProto(pt)
&& pt != SingletonTypeProto
&& pt != LhsProto
&& !isRetainsArg(pt)
&& !ctx.mode.is(Mode.Pattern)
&& !tree.isInstanceOf[SplicePattern]
&& !ctx.isAfterTyper
Expand Down
12 changes: 10 additions & 2 deletions library/src/scala/annotation/retains.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@ package scala.annotation
* non-standard capturing type syntax.
*/
@experimental
class retains(xs: Any*) extends annotation.StaticAnnotation
class retains(xs: (Any@retainsArg)*) extends annotation.StaticAnnotation

/** Equivalent in meaning to `@retains(cap)`, but consumes less bytecode.
/** Equivalent in meaning to `@retains(cap)`, but consumes less bytecode.
*/
@experimental
class retainsCap() extends annotation.StaticAnnotation
// This special case is needed to be able to load standard library modules without
// cyclic reference errors. Specifically, load sequences involving IterableOnce.

/** Internal use, only for parameters of `retains` and `retainsByName`.
*/
@experimental
class retainsArg extends annotation.StaticAnnotation
// This annotation prevents argument references to retains and retainsByName from being
// augmented with explicit arguments. That's unsound in general, but necessary
// since a captureRef could have an impure context function type, A ?=> B, but
// we still need to have the unapplied captureRef in the annotation.
2 changes: 1 addition & 1 deletion library/src/scala/annotation/retainsByName.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package scala.annotation

/** An annotation that indicates capture of an enclosing by-name type
*/
@experimental class retainsByName(xs: Any*) extends annotation.StaticAnnotation
@experimental class retainsByName(xs: (Any@retainsArg)*) extends annotation.StaticAnnotation

4 changes: 4 additions & 0 deletions tests/pos-custom-args/captures/i20231.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Async
class C(val x: Async ?=> Unit)
def foo(x: Async ?=> Unit): C^{x} = C(x)
def foo(x: Async ?=> Unit)(using Async): C^{x} = C(x)
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ val experimentalDefinitionInLibrary = Set(
"scala.annotation.retains",
"scala.annotation.retainsByName",
"scala.annotation.retainsCap",
"scala.annotation.retainsArg",
"scala.Pure",
"scala.caps",
"scala.caps$",
Expand Down

0 comments on commit 75f38b5

Please sign in to comment.