Skip to content

Commit b17ef26

Browse files
committed
Tighten subsume rules for existentials
1. cap no longer subsumes existential variables 2. existential variables don't subsume other existential variables Still open: Existential variables should only subsume other capabilties if these are sharable capabilities.
1 parent 30971b5 commit b17ef26

File tree

4 files changed

+7
-17
lines changed

4 files changed

+7
-17
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureOps.scala

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -584,15 +584,6 @@ extension (tp: Type)
584584
case tp: ThisType => tp.cls.ccLevel.nextInner
585585
case _ => undefinedLevel
586586

587-
/** Is this a method or function that has `other` as its direct or indirect result
588-
* type?
589-
*/
590-
def hasSuffix(other: MethodType)(using Context): Boolean =
591-
(tp eq other) || tp.match
592-
case defn.RefinedFunctionOf(mt) => mt.hasSuffix(other)
593-
case mt: MethodType => mt.resType.hasSuffix(other)
594-
case _ => false
595-
596587
extension (tp: MethodType)
597588
/** A method marks an existential scope unless it is the prefix of a curried method */
598589
def marksExistentialScope(using Context): Boolean =

compiler/src/dotty/tools/dotc/cc/CaptureRef.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,10 @@ trait CaptureRef extends TypeProxy, ValueType:
264264
|| !y.stripReadOnly.isCap && !yIsExistential && canAddHidden && vs.addHidden(hidden, y)
265265
case Existential.Vble(binder) =>
266266
y.stripReadOnly match
267-
case Existential.Vble(binder1) => binder1.hasSuffix(binder)
268-
.showing(i"cmp existential $binder maxSubsumes $binder1 = $result", capt)
267+
case Existential.Vble(binder1) => false
269268
case _ => true
270269
case _ =>
271-
this.isCap /*&& !yIsExistential*/ && canAddHidden && vs != VarState.HardSeparate
270+
this.isCap && !yIsExistential && canAddHidden && vs != VarState.HardSeparate
272271
|| y.match
273272
case ReadOnlyCapability(y1) => this.stripReadOnly.maxSubsumes(y1, canAddHidden)
274273
case _ => false

tests/neg-custom-args/captures/unsound-reach-3.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ def withFile[R](path: String)(op: File^ => R): R = ???
1010
trait Foo[+X]:
1111
def use(@consume x: File^): X
1212
class Bar extends Foo[File^]: // error
13-
def use(@consume x: File^): File^ = x
13+
def use(@consume x: File^): File^ = x // error override
1414

1515
def bad(): Unit =
1616
val backdoor: Foo[File^] = new Bar // error (follow-on, since the parent Foo[File^] of bar is illegal).
1717
val boom: Foo[File^{backdoor*}] = backdoor
1818

1919
var escaped: File^{backdoor*} = null
2020
withFile("hello.txt"): f =>
21-
escaped = boom.use(f) // error
22-
// boom.use: (x: File^) -> File^{backdoor*}, it is a selection so reach capabilities are allowed
21+
escaped = boom.use(f) // error: separation
22+
// was boom.use: (x: File^) -> File^{backdoor*}, it is a selection so reach capabilities are allowed
2323
// f: File^, so there is no reach capabilities
2424

tests/neg-custom-args/captures/unsound-reach-4.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
-- [E164] Declaration Error: tests/neg-custom-args/captures/unsound-reach-4.scala:17:6 ---------------------------------
1414
17 | def use(@consume x: F): File^ = x // error @consume override
1515
| ^
16-
|error overriding method use in trait Foo of type (x: File^): box File^;
17-
| method use of type (x: File^): File^ has a parameter x with different @consume status than the corresponding parameter in the overridden definition
16+
| error overriding method use in trait Foo of type (x: File^): box File^;
17+
| method use of type (x: File^): File^ has incompatible type
1818
|
1919
| longer explanation available when compiling with `-explain`

0 commit comments

Comments
 (0)