-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Copy @use
and @consume
annotations to parameter types
#23324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4b0f18c
921a930
b867b3f
531d165
0dd57f2
1cf238f
9bdf3a7
3dcaf59
1d3c55a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -395,6 +395,9 @@ extension (tp: Type) | |
RefinedType(tp, name, | ||
AnnotatedType(rinfo, Annotation(defn.RefineOverrideAnnot, util.Spans.NoSpan))) | ||
|
||
def dropUseAndConsumeAnnots(using Context): Type = | ||
tp.dropAnnot(defn.UseAnnot).dropAnnot(defn.ConsumeAnnot) | ||
|
||
extension (tp: MethodType) | ||
/** A method marks an existential scope unless it is the prefix of a curried method */ | ||
def marksExistentialScope(using Context): Boolean = | ||
|
@@ -490,18 +493,24 @@ extension (sym: Symbol) | |
def hasTrackedParts(using Context): Boolean = | ||
!CaptureSet.ofTypeDeeply(sym.info).isAlwaysEmpty | ||
|
||
/** `sym` is annotated @use or it is a type parameter with a matching | ||
/** `sym` itself or its info is annotated @use or it is a type parameter with a matching | ||
* @use-annotated term parameter that contains `sym` in its deep capture set. | ||
*/ | ||
def isUseParam(using Context): Boolean = | ||
sym.hasAnnotation(defn.UseAnnot) | ||
|| sym.info.hasAnnotation(defn.UseAnnot) | ||
|| sym.is(TypeParam) | ||
&& sym.owner.rawParamss.nestedExists: param => | ||
param.is(TermParam) && param.hasAnnotation(defn.UseAnnot) | ||
&& param.info.deepCaptureSet.elems.exists: | ||
case c: TypeRef => c.symbol == sym | ||
case _ => false | ||
|
||
/** `sym` or its info is annotated with `@consume`. */ | ||
def isConsumeParam(using Context): Boolean = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried to drop the check but the tests failed. I think we still need it because there are cases when we check whether a symbol is declared There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, let's leave it in then. |
||
sym.hasAnnotation(defn.ConsumeAnnot) | ||
|| sym.info.hasAnnotation(defn.ConsumeAnnot) | ||
|
||
def isUpdateMethod(using Context): Boolean = | ||
sym.isAllOf(Mutable | Method, butNot = Accessor) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import language.experimental.captureChecking | ||
import caps.* | ||
|
||
class Runner(val x: Int) extends AnyVal: | ||
def runOps(@use ops: List[() => Unit]): Unit = | ||
ops.foreach(_()) // ok | ||
|
||
class RunnerAlt(val x: Int): | ||
def runOps(@use ops: List[() => Unit]): Unit = | ||
ops.foreach(_()) // ok, of course | ||
|
||
class RunnerAltAlt(val x: Int) extends AnyVal: | ||
def runOps(ops: List[() => Unit]): Unit = | ||
ops.foreach(_()) // error, as expected | ||
|
||
class RunnerAltAltAlt(val x: Int): | ||
def runOps(ops: List[() => Unit]): Unit = | ||
ops.foreach(_()) // error, as expected |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import language.experimental.captureChecking | ||
import caps.* | ||
trait Ref extends Mutable | ||
def kill(@consume x: Ref^): Unit = () | ||
|
||
class C1: | ||
def myKill(@consume x: Ref^): Unit = kill(x) // ok | ||
|
||
class C2(val dummy: Int) extends AnyVal: | ||
def myKill(@consume x: Ref^): Unit = kill(x) // ok, too | ||
|
||
class C3: | ||
def myKill(x: Ref^): Unit = kill(x) // error | ||
|
||
class C4(val dummy: Int) extends AnyVal: | ||
def myKill(x: Ref^): Unit = kill(x) // error, too |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,21 @@ | ||
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:8:6 ---------------------------------- | ||
8 | def foo(x: C): C // error | ||
| ^ | ||
|error overriding method foo in trait A of type (x: C): C; | ||
|error overriding method foo in trait A of type (@use x: C): C; | ||
| method foo of type (x: C): C has a parameter x with different @use status than the corresponding parameter in the overridden definition | ||
| | ||
| longer explanation available when compiling with `-explain` | ||
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:9:6 ---------------------------------- | ||
9 | def bar(@use x: C): C // error | ||
| ^ | ||
|error overriding method bar in trait A of type (x: C): C; | ||
| method bar of type (x: C): C has a parameter x with different @use status than the corresponding parameter in the overridden definition | ||
| method bar of type (@use x: C): C has a parameter x with different @use status than the corresponding parameter in the overridden definition | ||
| | ||
| longer explanation available when compiling with `-explain` | ||
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:15:15 -------------------------------- | ||
15 |abstract class C extends A[C], B2 // error | ||
| ^ | ||
|error overriding method foo in trait A of type (x: C): C; | ||
|error overriding method foo in trait A of type (@use x: C): C; | ||
| method foo in trait B2 of type (x: C): C has a parameter x with different @use status than the corresponding parameter in the overridden definition | ||
| | ||
| longer explanation available when compiling with `-explain` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import language.experimental.captureChecking | ||
trait IterableOnce[+T] | ||
trait Iterable[+T] extends IterableOnce[T]: | ||
def flatMap[U](@caps.use f: T => IterableOnce[U]^): Iterable[U]^{this, f*} | ||
|
||
|
||
class IterableOnceExtensionMethods[T](val it: IterableOnce[T]) extends AnyVal: | ||
def flatMap[U](@caps.use f: T => IterableOnce[U]^): IterableOnce[U]^{f*} = it match | ||
case it: Iterable[T] => it.flatMap(f) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need the
sym.hasAnnotation(...)
part? If not it's better to remove that clause.