Cache ResultCaps#23198
Merged
Linyxus merged 10 commits intoscala:mainfrom May 21, 2025
Merged
Conversation
Linyxus
reviewed
May 20, 2025
Contributor
Linyxus
left a comment
There was a problem hiding this comment.
LGTM!
however, the soundness issue I mentioned does compile on the branch too:
import language.experimental.captureChecking
trait Cap
case class Id[X](x: X)
def mkId[X](x: X): Id[X] = Id(x)
def withCap[X](op: (lcap: Cap^) => () => X): X = ???
def bar() =
val f = (lcap: Cap^) => () => mkId(lcap)
val leak = withCap(f)
val leaked = leak.xSeems to be related to capture sets for inferred types.
Contributor
|
The tree after cc: note that |
Contributor
Author
Two observations:
|
Note i15923 does not signal a leak anymore. I moved it and some variants to pending. Note: There seems to be something more fundamentally wrong with this test: We get an infinite recursion for variant i15923b.
There was some accidental type confusion which made every capture root type end up with cap as pathRoot and caps as pathOwner.
Split out Capability from Type. For now we keep most of the overall structure. E.g. capability handling code is in file CaptureRef.scala. We will change this afterwards in separate refactorings.
Fixes scala#23170 This was disabled before. We also had to slightly extend fresh/cap collapsing to make override checks go through under the new scheme.
This fixes problems encountered in scala#15923 where we got infinite recursions caused by infinite streams of new ResultCap instances that were added to capture sets. The analysis of the problem showed that there is a cycle of dependencies involving both forwards and backwards propagations of ResultCap instances between BiMapped capture sets linked by SubstBindingMaps. Each propagation would create a new derived ResultCap instance. We could try to solve the problem by having SubstBindingMaps remember their mappings and have their inverses work backwards. But that could still produce an infinite stream if there was a cycle of SubstBindingMaps of length > 2. So we fix the problem at the root by allowing only one derived ResultCap instance per original ResultCap / binder pair. Fixes scala#15923
A dependent function is represented as a refinement type with a normal applied function type as parent. When capture checking two dependent function types, the parents should be ignored. But there was a case where this did not happen: If the left hand side is a sinletontype with a capturing type over a dependent function type, and the original method type comparisons fail, then the parent type of the left hand type was tried as a fallback. This commit adds a test that prevents the fallback.
This was referenced May 21, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This fixes problems encountered for #15923 where we got infinite recursions
caused by infinite streams of new ResultCap instances that were added to capture sets.
The analysis of the problem showed that there is a cycle of dependencies involving
both forwards and backwards propagations of ResultCap instances between
BiMapped capture sets linked by SubstBindingMaps. Each propagation would
create a new derived ResultCap instance.
We could try to solve the problem by having SubstBindingMaps remember their mappings
and have their inverses work backwards. But that could still produce an infinite stream
if there was a cycle of SubstBindingMaps of length > 2. So we fix the problem at the
root by allowing only one derived ResultCap instance per original ResultCap / binder pair.
Fixes #15923
Based on #23184. Only last commit is new.