Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix i19315: avoid calling
addOuterRefs
when the actual type is box-…
…adapted (#19323) Fixes #19315. The unsound code: ```scala import language.experimental.captureChecking trait Logger case class Boxed[T](unbox: T) // a horrible function, but it typechecks def magic(l: Logger^): Logger = class Foo: def foo: Boxed[Logger^{this}] = // for the following line to typecheck // the capture checker assumes {l} <: {this} Boxed[Logger^{this}](l) val x = new Foo val y = x.foo.unbox // y: Logger^{x} val z: Logger = y // now the capability becomes pure z ``` The `magic` function typechecks before this fix. It casts a capability to a pure value, which is clearly unsound. The crux of the problem is `Boxed[Logger^{this}](l)`, which relies on the subcapturing relation `{l} <: {this}` enabled by the trick implemented `addOuterRefs`. `addOuterRefs` augment a capture set that contains a self reference (like `{this}`) with all outer references reachable from `this`. In this case, the augmented set is `{this, l}`. The reasoning is that, any captured outer references in the class can be rewritten into a field, thus being a subcapture of `{this}`: ``` class Foo: val this_l: Logger^{l} = l def foo: Boxed[Logger^{this}] = Boxed(this.this_l) ``` But the problem with this unsound example is that, the reference to `l` is boxed, so `l` is not captured by the class. Therefore, the above rewriting mismatches with the actual situation. This PR proposes a simple fix, which simply disable `addOuterRefs` when box adaptation happens. This is of course imprecise, but all tests pass with this fix.
- Loading branch information