Skip to content

Commit

Permalink
Fixes scala#22437
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bracevac committed Jan 27, 2025
1 parent f7e5df5 commit 965589b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/cc/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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

Expand Down
44 changes: 44 additions & 0 deletions tests/neg-custom-args/captures/capture-vars-subtyping2.scala
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 965589b

Please sign in to comment.