-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Description
Compiler version
3.6.4 and 3.7.0-RC1
Minimized code
import scala.util.boundary
import scala.annotation.constructorOnly
class Leak()(using @constructorOnly l: boundary.Label[String]) {
Seq("a", "b").foreach(_ => boundary.break("stop"))
}
Output
Compilation error
l is marked `@constructorOnly` but it is retained as a field in class Leak
Expectation
It should compile successfully, as the constructor argument shouldn't be captured.
Note
The compiler currently does capture the variable the moment it sees it passed to a lambda. Running CFR on the compiled code (when the annotation is not present), reveals:
import java.io.Serializable;
import scala.Function1;
import scala.collection.SeqOps;
import scala.collection.immutable.$colon$colon;
import scala.collection.immutable.List;
import scala.collection.immutable.Nil$;
import scala.runtime.Nothing$;
import scala.util.boundary;
import scala.util.boundary$;
public class Leak {
private final boundary.Label<String> l;
public Leak(boundary.Label<String> l) {
this.l = l;
((SeqOps)new $colon$colon<Nothing$>((Nothing$)((Object)"a"), (List<Nothing$>)new $colon$colon<Nothing$>((Nothing$)((Object)"b"), Nil$.MODULE$))).foreach((Function1<String, Object> & Serializable)_$1 -> {
throw boundary$.MODULE$.break("stop", l);
});
}
}
where one can see that this.l
is indeed never used, the Lambda simply closes over the constructor argument as expected.
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
rcano commentedon May 27, 2025
I'd like to clarify, the bug is not about the annotation misfiring, but the compiler violating expectation and retaining the field.
som-snytt commentedon May 29, 2025
In Scala 2, the lambda uses the instance field, so perhaps this is residual behavior.
som-snytt commentedon May 29, 2025
The member starts out captured. The field is dropped if it is only used from the constructor. For the lambda case, lambda construction must happen before the constructor finishes.