You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Infer `tracked` for parameters that are referenced in the public
signatures of the defining class.
e.g.
```scala 3
class OrdSet(val ord: Ordering) {
type Set = List[ord.T]
def empty: Set = Nil
implicit class helper(s: Set) {
def add(x: ord.T): Set = x :: remove(x)
def remove(x: ord.T): Set = s.filter(e => ord.compare(x, e) != 0)
def member(x: ord.T): Boolean = s.exists(e => ord.compare(x, e) == 0)
}
}
```
In the example above, `ord` is referenced in the signatures of the
public members of `OrdSet`, so a `tracked` modifier will be inserted
automatically.
Aldo generalize the condition for infering tracked for context bounds.
Explicit `using val` witnesses will now also be `tracked` by default.
This implementation should be safe with regards to not introducing
spurious cyclic reference errors.
Current limitations (I'll create separate issues for them, once this is
merged):
- Inferring `tracked` for given classes is done after the desugaring to
class + def, so the def doesn't know about `tracked` being set on the
original constructor parameter. This might be worked around by watching
the original symbol or adding an attachment pointer to the implicit
wrapper.
```scala 3
given mInst: (c: C) => M:
def foo: c.T = c.foo
```
- Passing parameters as an **inferred** `tracked` arguments in parents
doesn't work, since forcing a parent (term) isn't safe.
This can be replaced with a lint that is checked after Namer.
In the example above, `ord` is referenced in the signatures of the public
137
+
members of `OrdSet`, so a `tracked` modifier will be inserted automatically.
138
+
139
+
Another common case is when a context bound has an associated type (i.e. an abstract type member) e.g.
140
+
```scala 3
141
+
traitTC:
142
+
typeSelf
143
+
typeT
144
+
145
+
classKlass[A: {TCastc}]
146
+
```
147
+
148
+
Here, `tc` is a context bound with an associated type `T`, so `tracked` will be inferred for `tc`.
149
+
150
+
### Discussion
112
151
113
152
Since `tracked` is so useful, why not assume it by default? First, `tracked` makes sense only for `val` parameters. If a class parameter is not also a field declared using `val` then there's nothing to refine in the constructor result type. One could think of at least making all `val` parameters tracked by default, but that would be a backwards incompatible change. For instance, the following code would break:
0 commit comments