Skip to content

Commit c662bc3

Browse files
committed
Re-use `NamerOps.methodType when computing initial types of methods
No need to construct a complicated BiTypeMap anymore.
1 parent 90cee43 commit c662bc3

File tree

9 files changed

+70
-16
lines changed

9 files changed

+70
-16
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ object ccConfig:
5555

5656
/** Not used currently. Handy for trying out new features */
5757
def newScheme(using Context): Boolean =
58-
Feature.sourceVersion.stable.isAtLeast(SourceVersion.`3.8`)
58+
Feature.sourceVersion.stable.isAtLeast(SourceVersion.`3.7`)
5959

6060
end ccConfig
6161

@@ -259,7 +259,8 @@ extension (tp: Type)
259259
case tp: TypeRef =>
260260
tp.symbol.isType && tp.derivesFrom(defn.Caps_CapSet)
261261
case tp: TypeParamRef =>
262-
tp.derivesFrom(defn.Caps_CapSet)
262+
!tp.underlying.exists // might happen during construction of lambdas
263+
|| tp.derivesFrom(defn.Caps_CapSet)
263264
case root.Result(_) => true
264265
case AnnotatedType(parent, annot) =>
265266
defn.capabilityWrapperAnnots.contains(annot.symbol) && parent.isTrackableRef

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ trait CaptureRef extends TypeProxy, ValueType:
135135
else
136136
myCaptureSet = CaptureSet.Pending
137137
val computed = CaptureSet.ofInfo(this)
138-
if !isCaptureChecking || ctx.mode.is(Mode.IgnoreCaptures) || underlying.isProvisional then
138+
if !isCaptureChecking
139+
|| ctx.mode.is(Mode.IgnoreCaptures)
140+
|| !underlying.exists
141+
|| underlying.isProvisional
142+
then
139143
myCaptureSet = null
140144
else
141145
myCaptureSet = computed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,13 @@ sealed abstract class CaptureSet extends Showable:
341341
if isConst then
342342
if mapped.isConst && mapped.elems == elems && !mapped.keepAlways then this
343343
else mapped
344-
else Mapped(asVar, tm, tm.variance, mapped)
344+
else if ccConfig.newScheme then
345+
if mapped.elems == elems then this
346+
else
347+
asVar.markSolved(provisional = true)
348+
mapped
349+
else
350+
Mapped(asVar, tm, tm.variance, mapped)
345351

346352
/** A mapping resulting from substituting parameters of a BindingType to a list of types */
347353
def substParams(tl: BindingType, to: List[Type])(using Context) =
@@ -1339,6 +1345,10 @@ object CaptureSet:
13391345
.showing(i"Deep capture set of $ref: ${ref1.widen} = ${result}", capt)
13401346
case ReadOnlyCapability(ref1) =>
13411347
ref1.captureSetOfInfo.map(ReadOnlyMap())
1348+
case ref: ParamRef if !ref.underlying.exists =>
1349+
// might happen during construction of lambdas, assume `{cap}` in this case so that
1350+
// `ref` will not seem subsumed by other capabilities in a `++`.
1351+
universal
13421352
case _ =>
13431353
if ref.isRootCapability then ref.singletonCaptureSet
13441354
else ofType(ref.underlying, followResult = false)

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -702,24 +702,41 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
702702
if prevLambdas.isEmpty then resType
703703
else SubstParams(prevPsymss, prevLambdas)(resType)
704704

705+
def paramsToCap(mt: Type)(using Context): Type = mt match
706+
case mt: MethodType =>
707+
mt.derivedLambdaType(
708+
paramInfos = mt.paramInfos.map(root.freshToCap),
709+
resType = paramsToCap(mt.resType))
710+
case mt: PolyType =>
711+
mt.derivedLambdaType(resType = paramsToCap(mt.resType))
712+
case _ => mt
713+
705714
// If there's a change in the signature, update the info of `sym`
706715
if sym.exists && signatureChanges then
707716
val updatedInfo =
708717
if ccConfig.newScheme then
709-
def newInfo = root.toResultInResults(report.error(_, tree.srcPos)):
710-
if sym.is(Method) then methodType(sym.paramSymss, localReturnType)
711-
else tree.tpt.nuType
718+
val paramSymss = sym.paramSymss
719+
def newInfo(using Context) = // will be run in this or next phase
720+
root.toResultInResults(report.error(_, tree.srcPos)):
721+
if sym.is(Method) then
722+
paramsToCap(methodType(paramSymss, localReturnType))
723+
else tree.tpt.nuType
712724
if tree.tpt.isInstanceOf[InferredTypeTree]
713725
&& !sym.is(Param) && !sym.is(ParamAccessor)
714726
then
715727
val prevInfo = sym.info
716728
new LazyType:
717729
def complete(denot: SymDenotation)(using Context) =
718730
assert(ctx.phase == thisPhase.next, i"$sym")
719-
capt.println(i"forcing $sym, printing = ${ctx.mode.is(Mode.Printing)}")
720731
sym.info = prevInfo // set info provisionally so we can analyze the symbol in recheck
721732
completeDef(tree, sym, this)
722733
sym.info = newInfo
734+
.showing(i"new info of $sym = $result", capt)
735+
else if sym.is(Method) then
736+
new LazyType:
737+
def complete(denot: SymDenotation)(using Context) =
738+
sym.info = newInfo
739+
.showing(i"new info of $sym = $result", capt)
723740
else newInfo
724741
else
725742
val newInfo =

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4715,7 +4715,7 @@ object Types extends TypeUtils {
47154715
override def hashIsStable: Boolean = false
47164716
}
47174717

4718-
abstract class ParamRef extends BoundType {
4718+
abstract class ParamRef extends BoundType, CaptureRef {
47194719
type BT <: LambdaType
47204720
def paramNum: Int
47214721
def paramName: binder.ThisName = binder.paramNames(paramNum)
@@ -4762,7 +4762,7 @@ object Types extends TypeUtils {
47624762
* refer to `TypeParamRef(binder, paramNum)`.
47634763
*/
47644764
abstract case class TypeParamRef(binder: TypeLambda, paramNum: Int)
4765-
extends ParamRef, CaptureRef {
4765+
extends ParamRef {
47664766
type BT = TypeLambda
47674767
def kindString: String = "Type"
47684768
def copyBoundType(bt: BT): Type = bt.paramRefs(paramNum)

tests/neg-custom-args/captures/heal-tparam-cs.check

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,30 @@
1515
| ^
1616
| Found: (x$0: Capp^?) ->? () ->{x$0} Unit
1717
| Required: (c: Capp^) -> () ->{localcap} Unit
18-
|
19-
| Note that reference <cap of (x$0: Capp^?): () ->{x$0} Unit>
20-
| cannot be included in outer capture set {x$0}
2118
16 | (c1: Capp^) => () => { c1.use() }
2219
17 | }
2320
|
2421
| longer explanation available when compiling with `-explain`
22+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/heal-tparam-cs.scala:20:13 -------------------------------
23+
20 | localCap { c => // error (???) since change to cs mapping
24+
| ^
25+
| Found: (x$0: Capp^?) ->? () ->{x$0} Unit
26+
| Required: (c: Capp^{io}) -> () ->{io} Unit
27+
|
28+
| Note that the existential capture root in () ->? Unit
29+
| cannot subsume the capability <cap of (c1: Capp^?): () ->{c1} Unit>
30+
21 | (c1: Capp^{io}) => () => { c1.use() }
31+
22 | }
32+
|
33+
| longer explanation available when compiling with `-explain`
2534
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/heal-tparam-cs.scala:25:13 -------------------------------
2635
25 | localCap { c => // error
2736
| ^
28-
| Found: (x$0: Capp^{io}) ->? () ->{x$0, io} Unit
37+
| Found: (x$0: Capp^?) ->? () ->{x$0} Unit
2938
| Required: (c: Capp^{io}) -> () ->{net} Unit
39+
|
40+
| Note that the existential capture root in () ->? Unit
41+
| cannot subsume the capability <cap of (c1: Capp^?): () ->{c1} Unit>
3042
26 | (c1: Capp^{io}) => () => { c1.use() }
3143
27 | }
3244
|

tests/neg-custom-args/captures/heal-tparam-cs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def main(io: Capp^, net: Capp^): Unit = {
1717
}
1818

1919
val test3: (c: Capp^{io}) -> () ->{io} Unit =
20-
localCap { c => // ok
20+
localCap { c => // error (???) since change to cs mapping
2121
(c1: Capp^{io}) => () => { c1.use() }
2222
}
2323

tests/neg-custom-args/captures/usingLogFile.check

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,13 @@
2828
| cannot be included in outer capture set ?
2929
|
3030
| longer explanation available when compiling with `-explain`
31+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/usingLogFile.scala:52:6 ----------------------------------
32+
52 | usingLogger(_, l => () => l.log("test"))) // error after checking mapping scheme
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
| Found: (_$1: java.io.OutputStream^) ->? box () ->{_$1} Unit
35+
| Required: (_$1: java.io.OutputStream^) ->{fresh} box () ->? Unit
36+
|
37+
| Note that reference _$1.type
38+
| cannot be included in outer capture set ?
39+
|
40+
| longer explanation available when compiling with `-explain`

tests/neg-custom-args/captures/usingLogFile.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ object Test3:
4949

5050
def test =
5151
val later = usingFile("logfile", // now ok
52-
usingLogger(_, l => () => l.log("test")))
52+
usingLogger(_, l => () => l.log("test"))) // error after checking mapping scheme
5353
later()

0 commit comments

Comments
 (0)