Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CapSet Type-Variable Bounds Crash the Capture Checker #22437

Open
bracevac opened this issue Jan 22, 2025 · 3 comments · May be fixed by #22451
Open

CapSet Type-Variable Bounds Crash the Capture Checker #22437

bracevac opened this issue Jan 22, 2025 · 3 comments · May be fixed by #22451
Assignees
Labels
area:experimental:cc Capture checking related cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug itype:crash

Comments

@bracevac
Copy link
Contributor

bracevac commented Jan 22, 2025

Compiler version

Latest nightly

Minimized code

With the recents improvements involving capture variables, we now have two ways to write down a capture variable's bounds, e.g.,

def mixedBounds[A^, B >: CapSet <: A, C >: CapSet <: CapSet^{B^}] = ???

C's bound can also be written as simply <: B. However, with the bound
<: CapSet^{B^} the setup phase of the capture checker crashes while
executing the integrateRT method.

It would be nice to support the CapSet^{B^} notation, since one expects
to be able to provide a non-singleton bound, e.g., C <: CapSet^{a,b,c}.

Output (click arrow to expand)

Exception in thread "main" java.lang.AssertionError: assertion failed: not a trackable captureRef ref: B, [B, <notype>]

  unhandled exception while running cc on tests/neg-custom-args/captures/capture-vars-subtyping.scala

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/scala/scala3/issues/new/choose
  For non-enriched exceptions, compile with -Xno-enrich-error-messages.


     while compiling: local/capture-bounds.scala
        during phase: cc
                mode: Mode(ImplicitsEnabled)
     library version: version 2.13.16
    compiler version: version 3.7.0-RC1-bin-SNAPSHOT-nonbootstrapped-git-c3fcd7c
            settings: -classpath /Users/oliver/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar:/Users/oliver/projects/scala3/library/../out/bootstrap/scala3-library-bootstrapped/scala-3.7.0-RC1-bin-SNAPSHOT-nonbootstrapped/scala3-library_3-3.7.0-RC1-bin-SNAPSHOT.jar -d /Users/oliver/projects/scala3/compiler/../out/default-last-scalac-out.jar

        at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
        at dotty.tools.dotc.core.Types$BiTypeMap.ensureTrackable$1(Types.scala:6085)
        at dotty.tools.dotc.core.Types$BiTypeMap.forward(Types.scala:6086)
        at dotty.tools.dotc.core.Types$BiTypeMap.forward$(Types.scala:6069)
        at dotty.tools.dotc.cc.Setup$SubstParams.forward(Setup.scala:384)
        at dotty.tools.dotc.cc.CaptureSet.$anonfun$6(CaptureSet.scala:293)
        at dotty.tools.dotc.util.SimpleIdentitySet$Set1.map(SimpleIdentitySet.scala:86)
        at dotty.tools.dotc.cc.CaptureSet.map(CaptureSet.scala:293)
        at dotty.tools.dotc.core.Types$TypeMap.mapCapturingType(Types.scala:6168)
        at dotty.tools.dotc.core.Types$TypeMap.mapOver(Types.scala:6221)
        at dotty.tools.dotc.cc.Setup$SubstParams.apply(Setup.scala:401)
        at dotty.tools.dotc.core.Types$TypeMap.mapOver(Types.scala:6212)
        at dotty.tools.dotc.cc.Setup$SubstParams.apply(Setup.scala:401)
        at dotty.tools.dotc.cc.Setup$$anon$4.integrateRT$1$$anonfun$1$$anonfun$1(Setup.scala:583)
        at scala.collection.immutable.List.map(List.scala:251)
        at dotty.tools.dotc.cc.Setup$$anon$4.integrateRT$1$$anonfun$1(Setup.scala:583)
        at dotty.tools.dotc.core.Types$PolyType.<init>(Types.scala:4346)
        at dotty.tools.dotc.core.Types$PolyType$.apply(Types.scala:4456)
        at dotty.tools.dotc.core.Types$PolyType$.apply(Types.scala:4453)
        at dotty.tools.dotc.cc.Setup$$anon$4.integrateRT$1(Setup.scala:586)
        at dotty.tools.dotc.cc.Setup$$anon$4.postProcess(Setup.scala:598)
        at dotty.tools.dotc.cc.Setup$$anon$4.traverse(Setup.scala:513)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1339)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.foldOver(Trees.scala:1760)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverseChildren(Trees.scala:1802)
        at dotty.tools.dotc.cc.Setup$$anon$4.traverse(Setup.scala:512)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.apply(Trees.scala:1801)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.apply(Trees.scala:1801)
        at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.foldOver(Trees.scala:1757)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverseChildren(Trees.scala:1802)
        at dotty.tools.dotc.cc.Setup$$anon$4.traverse(Setup.scala:502)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1339)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1340)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1337)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverse(Trees.scala:1800)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.recur$2(tpd.scala:1337)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1342)
        at dotty.tools.dotc.ast.tpd$TreeTraverserWithPreciseImportContexts.apply(tpd.scala:1334)
        at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.foldOver(Trees.scala:1766)
        at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverseChildren(Trees.scala:1802)
        at dotty.tools.dotc.cc.Setup$$anon$4.traverse(Setup.scala:512)
        at dotty.tools.dotc.cc.Setup.setupUnit(Setup.scala:837)
        at dotty.tools.dotc.cc.CheckCaptures$CaptureChecker.checkUnit(CheckCaptures.scala:1548)
        at dotty.tools.dotc.transform.Recheck.run(Recheck.scala:149)
        at dotty.tools.dotc.cc.CheckCaptures.run(CheckCaptures.scala:258)
        at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:383)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.immutable.List.foreach(List.scala:334)
        at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:376)
        at dotty.tools.dotc.transform.Recheck.runOn(Recheck.scala:153)
        at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:343)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1324)
        at dotty.tools.dotc.Run.runPhases$1(Run.scala:336)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:383)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:395)
        at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:395)
        at dotty.tools.dotc.Run.compileSources(Run.scala:282)
        at dotty.tools.dotc.Run.compile(Run.scala:267)
        at dotty.tools.dotc.Driver.doCompile(Driver.scala:37)
        at dotty.tools.dotc.Driver.process(Driver.scala:201)
        at dotty.tools.dotc.Driver.process(Driver.scala:169)
        at dotty.tools.dotc.Driver.process(Driver.scala:181)
        at dotty.tools.dotc.Driver.main(Driver.scala:211)
        at dotty.tools.dotc.Main.main(Main.scala)
@bracevac bracevac added area:experimental:cc Capture checking related cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug itype:crash labels Jan 22, 2025
@Linyxus
Copy link
Contributor

Linyxus commented Jan 24, 2025

I had a look. The problem seems to be with ensureTrackable in BiTypeMap at Types.scala: in integrateRT when mapping parameter references we use a BiTypeMap, which, when applied, calls ensureTrackable to assert that the results are trackable capture references. However, in integrateRT at this callsite, the info of TypeParamRef is not reliable (it seems to be NoType) as the lambda is still being formed. So this assertion always fails.

This assertion seems a sanity check, and not essential for checking the wellformedness of capture sets. Given that the info of TypeParamRef at that moment is not informative enough for us to properly perform this check, maybe we should fix this issue by temporarily disabling this assert?

bracevac added a commit to dotty-staging/dotty that referenced this issue Jan 24, 2025
Fixes scala#22437

The check crashes the compiler when mapping over a capture variable
in an upper bound of the form `CapSet^{C^}` as well as
path captures in function signatures. See the test
`capture-vars-subtyping2.scala` for examples.
@noti0na1
Copy link
Member

The current integrateRT is not able to handle depedent parameters (both type and term) in the same list, because the mapped ref is refering to a method type which is still under constructing.

@bracevac
Copy link
Contributor Author

bracevac commented Jan 25, 2025

It does work when we remove the isTrackableRef checks in BiTypeMap #22451. The change does not break any tests. Can we find an example that shows we need the retain the check?

Edit: I left the check in place, and instead skip it only for type and term refs that have no info.

bracevac added a commit to dotty-staging/dotty that referenced this issue Jan 27, 2025
The check crashes the compiler when mapping over a capture variable in
a type bound bound of the form
CapSet^{C^} as well as path captures in function signatures.
See the test capture-vars-subtyping2.scala for examples.
@bracevac bracevac self-assigned this Jan 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:experimental:cc Capture checking related cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug itype:crash
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants