diff --git a/compiler/src/dotty/tools/dotc/cc/Setup.scala b/compiler/src/dotty/tools/dotc/cc/Setup.scala index e28aeb8e0313..a5e96f1f9ce2 100644 --- a/compiler/src/dotty/tools/dotc/cc/Setup.scala +++ b/compiler/src/dotty/tools/dotc/cc/Setup.scala @@ -570,7 +570,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: // For example, `(x: T, y: x.f.type) => Unit`. In this case, when we // substitute `x.f.type`, `x` becomes a `TermParamRef`. But the new method // type is still under initialization and `paramInfos` is still `null`, - // so the new `NamedType` will not have a denoation. + // so the new `NamedType` will not have a denotation. def adaptedInfo(psym: Symbol, info: mt.PInfo): mt.PInfo = mt.companion match case mtc: MethodTypeCompanion => mtc.adaptParamInfo(psym, info).asInstanceOf[mt.PInfo] case _ => info diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 2fcf628dbc01..d98361bcdda9 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -6073,6 +6073,9 @@ object Types extends TypeUtils { def forward(ref: CaptureRef): CaptureRef = val result = this(ref) def ensureTrackable(tp: Type): CaptureRef = tp match + /* Issue #22437: handle case when info is not yet available during postProcess in CC setup */ + case tp: (TypeParamRef | TermRef) if tp.underlying == NoType => + tp case tp: CaptureRef => if tp.isTrackableRef then tp else ensureTrackable(tp.underlying) @@ -6084,6 +6087,9 @@ object Types extends TypeUtils { /** A restriction of the inverse to a function on tracked CaptureRefs */ def backward(ref: CaptureRef): CaptureRef = inverse(ref) match + /* Ensure bijection for issue #22437 fix in method forward above: */ + case result: (TypeParamRef | TermRef) if result.underlying == NoType => + result case result: CaptureRef if result.isTrackableRef => result end BiTypeMap 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