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
Here, the `test` method takes a `FileSystem` as a parameter. `fs` is a capability since its type has a non-empty capture set. The capability is passed the `Logger` constructor
116
+
Here, the `test` method takes a `FileSystem` as a parameter. `fs` is a capability since its type has a non-empty capture set. The capability is passed to the `Logger` constructor
117
117
and retained as a field in class `Logger`. Hence, the local variable `l` has type
118
118
`{fs} Logger`: it is a `Logger` which retains the `fs` capability.
119
119
@@ -223,7 +223,7 @@ was declared with a result type `LazyList[Int]`, we'd get a type error. Here is
223
223
| Found: {fs} LazyList[Int]
224
224
| Required: LazyList[Int]
225
225
```
226
-
Why does is say `{fs} LazyList[Int]` and not `{l} LazyList[Int]`, which is, after all, the type of the returned value `xs`? The reason is that `l` is a local variable in the body of `test`, so it cannot be referred to in a type outside that body. What happens instead is that the type is _widened_ to the smallest supertype that does not mention `l`. Since `l` has capture set `fs`, we have that `{fs}` covers `{l}`, and `{fs}` is acceptable as in a result type of `test`, so `{fs}` is the result of that widening.
226
+
Why does it say `{fs} LazyList[Int]` and not `{l} LazyList[Int]`, which is, after all, the type of the returned value `xs`? The reason is that `l` is a local variable in the body of `test`, so it cannot be referred to in a type outside that body. What happens instead is that the type is _widened_ to the smallest supertype that does not mention `l`. Since `l` has capture set `fs`, we have that `{fs}` covers `{l}`, and `{fs}` is acceptable in a result type of `test`, so `{fs}` is the result of that widening.
227
227
This widening is called _avoidance_; it is not specific to capture checking but applies to all variable references in Scala types.
228
228
229
229
## Capability Classes
@@ -277,7 +277,7 @@ itself does not refer to `fs`.
277
277
278
278
## Capture Checking of Classes
279
279
280
-
The principles for capture checking closures also applies to classes. For instance, consider:
280
+
The principles for capture checking closures also apply to classes. For instance, consider:
@@ -369,7 +369,7 @@ again on access, the capture information "pops out" again. For instance, even th
369
369
```scala
370
370
() => p.fst : {ct} () -> {ct} Int->String
371
371
```
372
-
In other words, references to capabilities "tunnel through" in generic instantiations from creation to access, they do not affect the capture set of the enclosing generic data constructor applications.
372
+
In other words, references to capabilities "tunnel through" in generic instantiations from creation to access; they do not affect the capture set of the enclosing generic data constructor applications.
373
373
This principle may seem surprising at first, but it is the key to make capture checking concise and practical.
374
374
375
375
## Escape Checking
@@ -429,7 +429,7 @@ val sneaky = usingLogFile { f => Cell(() => f.write(0)) }
429
429
sneaky.x()
430
430
```
431
431
At the point where the `Cell` is created, the capture set of the argument is `f`, which
432
-
is OK. But at the point of use, it is `*`, which causes again an error:
432
+
is OK. But at the point of use, it is `*` (because `f` is no longer in scope), which causes again an error:
433
433
```
434
434
| sneaky.x()
435
435
| ^^^^^^^^
@@ -662,14 +662,14 @@ Constraint variables stand for unknown capture sets. A constraint variable is in
662
662
663
663
Capture sets in explicitly written types are treated as constants (before capture checking, such sets are simply ignored).
664
664
665
-
The capture checker essentially rechecks the program with the usual typing rules. Every time a subtype requirement between capturing types is checked, this translates to a subcapturing test on capture sets. If the two sets are constant, this is simply as yes/no question, where a no will produce an error message.
665
+
The capture checker essentially rechecks the program with the usual typing rules. Every time a subtype requirement between capturing types is checked, this translates to a subcapturing test on capture sets. If the two sets are constant, this is simply a yes/no question, where a no will produce an error message.
666
666
667
667
If the lower set `C₁` of a comparison `C₁ <: C₂` is a variable, the set `C₂` is recorded
668
668
as a _superset_ of `C₁`. If the upper set `C₂` is a variable, the elements of `C₁` are _propagated_ to `C₂`. Propagation of an element `x` to a set `C` means that `x` is included as an element in `C`, and it is also propagated
669
669
to all known supersets of `C`. If such a superset is a constant, it is checked that `x` is included in it. If that's not the case, the original comparison `C₁ <: C₂` has no solution and an error is reported.
670
670
671
671
The type checker also performs various maps on types, for instance when substituting actual argument types for formal parameter types in dependent functions, or mapping
672
-
member types with as "as-seen-from" in a selection. Maps keep track of the variance
672
+
member types with "as-seen-from" in a selection. Maps keep track of the variance
673
673
of positions in a type. The variance is initially covariant, it flips to
674
674
contravariant in function parameter positions, and can be either covariant,
675
675
contravariant, or nonvariant in type arguments, depending on the variance of
0 commit comments