Skip to content

Commit c31c24d

Browse files
committed
Do fluidify when transforming symbols instead of on access
1 parent 1576b11 commit c31c24d

File tree

3 files changed

+51
-57
lines changed

3 files changed

+51
-57
lines changed

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

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -342,46 +342,14 @@ class CheckCaptures extends Recheck, SymTransformer:
342342
def includeCallCaptures(sym: Symbol, pos: SrcPos)(using Context): Unit =
343343
if sym.exists && curEnv.isOpen then markFree(capturedVars(sym), pos)
344344

345-
private def handleBackwardsCompat(tp: Type, sym: Symbol, initialVariance: Int = 1)(using Context): Type =
346-
val fluidify = new TypeMap with IdempotentCaptRefMap:
347-
variance = initialVariance
348-
def apply(t: Type): Type = t match
349-
case t: MethodType =>
350-
mapOver(t)
351-
case t: TypeLambda =>
352-
t.derivedLambdaType(resType = this(t.resType))
353-
case CapturingType(_, _) =>
354-
t
355-
case _ =>
356-
val t1 = t match
357-
case t @ defn.RefinedFunctionOf(rinfo: MethodType) =>
358-
t.derivedRefinedType(t.parent, t.refinedName, this(rinfo))
359-
case _ =>
360-
mapOver(t)
361-
if variance > 0 then t1
362-
else setup.decorate(t1, rootTarget = NoSymbol, addedSet = Function.const(CaptureSet.Fluid))
363-
364-
def isPreCC(sym: Symbol): Boolean =
365-
sym.isTerm && sym.maybeOwner.isClass
366-
&& !sym.owner.is(CaptureChecked)
367-
&& !defn.isFunctionSymbol(sym.owner)
368-
369-
if isPreCC(sym) then
370-
val tpw = tp.widen
371-
val fluidTp = fluidify(tpw)
372-
if fluidTp eq tpw then tp
373-
else fluidTp.showing(i"fluid for ${sym.showLocated}, ${sym.is(JavaDefined)}: $tp --> $result", capt)
374-
else tp
375-
end handleBackwardsCompat
376-
377345
override def recheckIdent(tree: Ident)(using Context): Type =
378346
if tree.symbol.is(Method) then
379347
if tree.symbol.info.isParameterless then
380348
// there won't be an apply; need to include call captures now
381349
includeCallCaptures(tree.symbol, tree.srcPos)
382350
else
383351
markFree(tree.symbol, tree.srcPos)
384-
handleBackwardsCompat(super.recheckIdent(tree), tree.symbol)
352+
super.recheckIdent(tree)
385353

386354
/** A specialized implementation of the selection rule.
387355
*
@@ -411,7 +379,7 @@ class CheckCaptures extends Recheck, SymTransformer:
411379
val selType = recheckSelection(tree, qualType, name, disambiguate)
412380
val selCs = selType.widen.captureSet
413381
if selCs.isAlwaysEmpty || selType.widen.isBoxedCapturing || qualType.isBoxedCapturing then
414-
handleBackwardsCompat(selType, tree.symbol)
382+
selType
415383
else
416384
val qualCs = qualType.captureSet
417385
capt.println(i"pick one of $qualType, ${selType.widen}, $qualCs, $selCs in $tree")
@@ -1025,9 +993,8 @@ class CheckCaptures extends Recheck, SymTransformer:
1025993
finally curEnv = saved
1026994
actual1 frozen_<:< expected1
1027995

1028-
override def adjustInfo(tp: Type, member: Symbol)(using Context): Type =
1029-
handleBackwardsCompat(tp, member, initialVariance = 0)
1030-
//.showing(i"adjust $other: $tp --> $result")
996+
override def needsCheck(overriding: Symbol, overridden: Symbol)(using Context): Boolean =
997+
!setup.isPreCC(overriding) && !setup.isPreCC(overridden)
1031998
end OverridingPairsCheckerCC
1032999

10331000
def traverse(t: Tree)(using Context) =

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import config.Feature
1111
import config.Printers.{capt, ccSetup}
1212
import ast.tpd, tpd.*
1313
import transform.{PreRecheck, Recheck}, Recheck.*
14-
import CaptureSet.IdentityCaptRefMap
14+
import CaptureSet.{IdentityCaptRefMap, IdempotentCaptRefMap}
1515
import Synthetics.isExcluded
1616
import util.Property
1717
import printing.{Printer, Texts}, Texts.{Text, Str}
@@ -21,7 +21,7 @@ import collection.mutable
2121
trait SetupAPI:
2222
type DefRecheck = (tpd.ValOrDefDef, Symbol) => Context ?=> Type
2323
def setupUnit(tree: Tree, recheckDef: DefRecheck)(using Context): Unit
24-
def decorate(tp: Type, rootTarget: Symbol, addedSet: Type => CaptureSet)(using Context): Type
24+
def isPreCC(sym: Symbol)(using Context): Boolean
2525

2626
object Setup:
2727
def newScheme(using Context) = ctx.settings.YccNew.value // if new impl is conditional
@@ -82,14 +82,36 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
8282
then symd.flags &~ Private | Recheck.ResetPrivate
8383
else symd.flags
8484

85+
def isPreCC(sym: Symbol)(using Context): Boolean =
86+
sym.isTerm && sym.maybeOwner.isClass
87+
&& !sym.is(Module)
88+
&& !sym.owner.is(CaptureChecked)
89+
&& !defn.isFunctionSymbol(sym.owner)
90+
91+
private def fluidify(using Context) = new TypeMap with IdempotentCaptRefMap:
92+
def apply(t: Type): Type = t match
93+
case t: MethodType =>
94+
mapOver(t)
95+
case t: TypeLambda =>
96+
t.derivedLambdaType(resType = this(t.resType))
97+
case CapturingType(_, _) =>
98+
t
99+
case _ =>
100+
val t1 = t match
101+
case t @ defn.RefinedFunctionOf(rinfo: MethodType) =>
102+
t.derivedRefinedType(t.parent, t.refinedName, this(rinfo))
103+
case _ =>
104+
mapOver(t)
105+
if variance > 0 then t1
106+
else decorate(t1, rootTarget = NoSymbol, addedSet = Function.const(CaptureSet.Fluid))
107+
85108
/** - Reset `private` flags of parameter accessors so that we can refine them
86109
* in Setup if they have non-empty capture sets.
87110
* - Special handling of some symbols defined for case classes.
88111
* Enabled only until recheck is finished, and provided some compilation unit
89112
* is CC-enabled.
90113
*/
91114
def transformSym(symd: SymDenotation)(using Context): SymDenotation =
92-
def needsInfoTransform = newScheme || symd.isGetter
93115
if !pastRecheck && Feature.ccEnabledSomewhere then
94116
val sym = symd.symbol
95117
val needsInfoTransform = sym.isDefinedInCurrentRun && !toBeUpdated.contains(sym)
@@ -98,6 +120,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
98120
// create local roots if necessary
99121
if Synthetics.needsTransform(symd) then
100122
Synthetics.transform(symd)
123+
else if isPreCC(sym) then
124+
symd.copySymDenotation(info = fluidify(sym.info))
101125
else if symd.owner.isTerm || symd.is(CaptureChecked) || symd.owner.is(CaptureChecked) then
102126
val newFlags = newFlagsFor(symd)
103127
val newInfo =

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -223,36 +223,39 @@ object RefChecks {
223223
false
224224
precedesIn(parent.asClass.baseClasses)
225225

226-
// We can exclude pairs safely from checking only under three additional conditions
227-
// - their signatures also match in the parent class.
228-
// See neg/i12828.scala for an example where this matters.
229-
// - They overriding/overridden appear in linearization order.
230-
// See neg/i5094.scala for an example where this matters.
231-
// - The overridden symbol is not `abstract override`. For such symbols
232-
// we need a more extensive test since the virtual super chain depends
233-
// on the precise linearization order, which might be different for the
234-
// subclass. See neg/i14415.scala.
226+
/** We can exclude pairs safely from checking only under three additional conditions
227+
* - their signatures also match in the parent class.
228+
* See neg/i12828.scala for an example where this matters.
229+
* - They overriding/overridden appear in linearization order.
230+
* See neg/i5094.scala for an example where this matters.
231+
* - The overridden symbol is not `abstract override`. For such symbols
232+
* we need a more extensive test since the virtual super chain depends
233+
* on the precise linearization order, which might be different for the
234+
* subclass. See neg/i14415.scala.
235+
*/
235236
override def canBeHandledByParent(sym1: Symbol, sym2: Symbol, parent: Symbol): Boolean =
236237
isOverridingPair(sym1, sym2, parent.thisType)
237238
.showing(i"already handled ${sym1.showLocated}: ${sym1.asSeenFrom(parent.thisType).signature}, ${sym2.showLocated}: ${sym2.asSeenFrom(parent.thisType).signature} = $result", refcheck)
238239
&& inLinearizationOrder(sym1, sym2, parent)
239240
&& !sym2.is(AbsOverride)
240241

241-
// Checks the subtype relationship tp1 <:< tp2.
242-
// It is passed to the `checkOverride` operation in `checkAll`, to be used for
243-
// compatibility checking.
242+
/** Checks the subtype relationship tp1 <:< tp2.
243+
* It is passed to the `checkOverride` operation in `checkAll`, to be used for
244+
* compatibility checking.
245+
*/
244246
def checkSubType(tp1: Type, tp2: Type)(using Context): Boolean = tp1 frozen_<:< tp2
245247

246-
/** A hook that allows to adjust the type of `member` and `other` before checking conformance.
248+
/** A hook that allows to omit override checks between `overriding` and `overridden`.
247249
* Overridden in capture checking to handle non-capture checked classes leniently.
248250
*/
249-
def adjustInfo(tp: Type, member: Symbol)(using Context): Type = tp
251+
def needsCheck(overriding: Symbol, overridden: Symbol)(using Context): Boolean = true
250252

251253
private val subtypeChecker: (Type, Type) => Context ?=> Boolean = this.checkSubType
252254

253255
def checkAll(checkOverride: ((Type, Type) => Context ?=> Boolean, Symbol, Symbol) => Unit) =
254256
while hasNext do
255-
checkOverride(subtypeChecker, overriding, overridden)
257+
if needsCheck(overriding, overridden) then
258+
checkOverride(subtypeChecker, overriding, overridden)
256259
next()
257260

258261
// The OverridingPairs cursor does assume that concrete overrides abstract
@@ -371,8 +374,8 @@ object RefChecks {
371374
def checkOverride(checkSubType: (Type, Type) => Context ?=> Boolean, member: Symbol, other: Symbol): Unit =
372375
def memberTp(self: Type) =
373376
if (member.isClass) TypeAlias(member.typeRef.EtaExpand(member.typeParams))
374-
else checker.adjustInfo(self.memberInfo(member), member)
375-
def otherTp(self: Type) = checker.adjustInfo(self.memberInfo(other), other)
377+
else self.memberInfo(member)
378+
def otherTp(self: Type) = self.memberInfo(other)
376379

377380
refcheck.println(i"check override ${infoString(member)} overriding ${infoString(other)}")
378381

0 commit comments

Comments
 (0)