From 81e05a28a8c1de13a5930b5a2097b27071fa5f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Bra=C4=8Devac?= Date: Fri, 24 Jan 2025 18:38:00 +0100 Subject: [PATCH] Do not check for trackable refs in BiTypeMap Fixes #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. --- .../src/dotty/tools/dotc/core/Types.scala | 5 ++- .../captures/capture-vars-subtyping2.scala | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/neg-custom-args/captures/capture-vars-subtyping2.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 2fcf628dbc01..69bad0212a09 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -6072,7 +6072,7 @@ object Types extends TypeUtils { /** A restriction of this map to a function on tracked CaptureRefs */ def forward(ref: CaptureRef): CaptureRef = val result = this(ref) - def ensureTrackable(tp: Type): CaptureRef = tp match + /*def ensureTrackable(tp: Type): CaptureRef = tp match case tp: CaptureRef => if tp.isTrackableRef then tp else ensureTrackable(tp.underlying) @@ -6080,7 +6080,8 @@ object Types extends TypeUtils { ensureTrackable(tp.alias) case _ => assert(false, i"not a trackable captureRef ref: $result, ${result.underlyingIterator.toList}") - ensureTrackable(result) + ensureTrackable(result)*/ + result.asInstanceOf[CaptureRef] /** A restriction of the inverse to a function on tracked CaptureRefs */ def backward(ref: CaptureRef): CaptureRef = inverse(ref) match diff --git a/tests/neg-custom-args/captures/capture-vars-subtyping2.scala b/tests/neg-custom-args/captures/capture-vars-subtyping2.scala new file mode 100644 index 000000000000..205451ee41ed --- /dev/null +++ b/tests/neg-custom-args/captures/capture-vars-subtyping2.scala @@ -0,0 +1,44 @@ +import language.experimental.captureChecking +import caps.* + +trait BoundsTest: + + trait Bar { val f: () => Unit } + def bar(x: Bar^, y: () ->{x.f} Unit): Unit = ??? + + val b: Bar^ = ??? + + def testTransMixed[A^, + B >: CapSet <: A, + C >: CapSet <: CapSet^{B^}, + D >: CapSet <: C, + E >: CapSet <: CapSet^{D^}, + F >: CapSet <: CapSet^{A^,b}, + X >: CapSet <: CapSet^{F^,D^}, + Y >: CapSet^{F^} <: CapSet^{F^,A^,b}, + Z >: CapSet^{b} <: CapSet^{b,Y^}] = + val e: E = ??? + val e2: CapSet^{E^} = e + val ed: D = e + val ed2: CapSet^{D^} = e + val ec: C = e + val ec2: CapSet^{C^} = e + val eb: B = e + val eb2: CapSet^{B^} = e + val ea: A = e + val ea2: CapSet^{A^} = e + val ex: X = e // error + val ex2: CapSet^{X^} = e // error + val f: F = ??? + val f2: CapSet^{F^} = f + val y: Y = f + val y2: CapSet^{Y^} = f + val cb: CapSet^{b} = ??? + val z: Z = cb + val z2: CapSet^{Z^} = cb + + def callTransMixed = + val x, y, z: Bar^ = ??? + testTransMixed[CapSet^{x,y,z}, CapSet^{x,y,z}, CapSet^{x,y,z}, CapSet^{x,y,z}, CapSet^{x,y,z}, CapSet^{x,y,z}, CapSet^{x,y,z}, CapSet^{x,y,z}, CapSet^{b,x,y,z}] + testTransMixed[CapSet^{x,y,z}, CapSet^{x,y}, CapSet^{x,y}, CapSet^{x}, CapSet^{}, CapSet^{b,x}, CapSet^{b}, CapSet^{b,x}, CapSet^{b}] + testTransMixed[CapSet^{x,y,z}, CapSet^{x,y}, CapSet^{x,y}, CapSet^{x}, CapSet^{}, CapSet^{b,x}, CapSet^{b}, CapSet^{b,x}, CapSet^{b,x,y,z}] // error