Skip to content

Commit 64e95b2

Browse files
committed
Also fluidify member when doing overriding checks
As `Map` shows, it's possible that an overriding check is from an external non-capture checked subclass member against a currently compiled & capture-checked superclass member. Hence, we have to add Fluid sets to either part of an overriding check if that part is not compiled with capture checking. This allows to include collection/Map in the set of capture checked stdlib sources.
1 parent fc9bb75 commit 64e95b2

File tree

3 files changed

+18
-18
lines changed

3 files changed

+18
-18
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ class CheckCaptures extends Recheck, SymTransformer:
311311

312312
def isPreCC(sym: Symbol): Boolean =
313313
sym.isTerm && sym.maybeOwner.isClass
314-
&& !defn.isFunctionSymbol(sym.owner)
315314
&& !sym.owner.is(CaptureChecked)
315+
&& !defn.isFunctionSymbol(sym.owner)
316316

317317
if isPreCC(sym) then
318318
val tpw = tp.widen
@@ -948,8 +948,8 @@ class CheckCaptures extends Recheck, SymTransformer:
948948
finally curEnv = saved
949949
actual1 frozen_<:< expected1
950950

951-
override def adjustOtherType(tp: Type, other: Symbol)(using Context): Type =
952-
handleBackwardsCompat(tp, other, initialVariance = 0)
951+
override def adjustInfo(tp: Type, member: Symbol)(using Context): Type =
952+
handleBackwardsCompat(tp, member, initialVariance = 0)
953953
//.showing(i"adjust $other: $tp --> $result")
954954
end OverridingPairsCheckerCC
955955

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,10 @@ object RefChecks {
239239
// compatibility checking.
240240
def checkSubType(tp1: Type, tp2: Type)(using Context): Boolean = tp1 frozen_<:< tp2
241241

242-
/** A hook that allows to adjust the type of `other` before checking conformance.
243-
* Overridden in capture checking to handle non-capture checked superclasses leniently.
242+
/** A hook that allows to adjust the type of `member` and `other` before checking conformance.
243+
* Overridden in capture checking to handle non-capture checked classes leniently.
244244
*/
245-
def adjustOtherType(tp: Type, other: Symbol)(using Context): Type = tp
245+
def adjustInfo(tp: Type, member: Symbol)(using Context): Type = tp
246246

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

@@ -367,8 +367,8 @@ object RefChecks {
367367
def checkOverride(checkSubType: (Type, Type) => Context ?=> Boolean, member: Symbol, other: Symbol): Unit =
368368
def memberTp(self: Type) =
369369
if (member.isClass) TypeAlias(member.typeRef.EtaExpand(member.typeParams))
370-
else self.memberInfo(member)
371-
def otherTp(self: Type) = checker.adjustOtherType(self.memberInfo(other), other)
370+
else checker.adjustInfo(self.memberInfo(member), member)
371+
def otherTp(self: Type) = checker.adjustInfo(self.memberInfo(other), other)
372372

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

tests/pos/stdlib/collection/Map.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import scala.annotation.nowarn
1717
import scala.collection.generic.DefaultSerializable
1818
import scala.collection.mutable.StringBuilder
1919
import scala.util.hashing.MurmurHash3
20-
//import language.experimental.captureChecking
20+
import language.experimental.captureChecking
2121

2222
/** Base Map type */
2323
trait Map[K, +V]
@@ -132,7 +132,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C]
132132
/** Similar to `fromIterable`, but returns a Map collection type.
133133
* Note that the return type is now `CC[K2, V2]`.
134134
*/
135-
@`inline` protected final def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]): CC[K2, V2] = mapFactory.from(it)
135+
@`inline` protected final def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]^): CC[K2, V2] = mapFactory.from(it)
136136

137137
/** The companion object of this map, providing various factory methods.
138138
*
@@ -319,7 +319,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C]
319319
* @return a new $coll resulting from applying the given collection-valued function
320320
* `f` to each element of this $coll and concatenating the results.
321321
*/
322-
def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] = mapFactory.from(new View.FlatMap(this, f))
322+
def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): CC[K2, V2] = mapFactory.from(new View.FlatMap(this, f))
323323

324324
/** Returns a new $coll containing the elements from the left hand operand followed by the elements from the
325325
* right hand operand. The element type of the $coll is the most specific superclass encompassing
@@ -329,15 +329,15 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C]
329329
* @return a new $coll which contains all elements
330330
* of this $coll followed by all elements of `suffix`.
331331
*/
332-
def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]): CC[K, V2] = mapFactory.from(suffix match {
332+
def concat[V2 >: V](suffix: collection.IterableOnce[(K, V2)]^): CC[K, V2] = mapFactory.from(suffix match {
333333
case it: Iterable[(K, V2)] => new View.Concat(this, it)
334334
case _ => iterator.concat(suffix.iterator)
335335
})
336336

337337
// Not final because subclasses refine the result type, e.g. in SortedMap, the result type is
338338
// SortedMap's CC, while Map's CC is fixed to Map
339339
/** Alias for `concat` */
340-
/*@`inline` final*/ def ++ [V2 >: V](xs: collection.IterableOnce[(K, V2)]): CC[K, V2] = concat(xs)
340+
/*@`inline` final*/ def ++ [V2 >: V](xs: collection.IterableOnce[(K, V2)]^): CC[K, V2] = concat(xs)
341341

342342
override def addString(sb: StringBuilder, start: String, sep: String, end: String): sb.type =
343343
iterator.map { case (k, v) => s"$k -> $v" }.addString(sb, start, sep, end)
@@ -351,14 +351,14 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C]
351351
mapFactory.from(new View.Concat(new View.Appended(new View.Appended(this, elem1), elem2), elems))
352352

353353
@deprecated("Consider requiring an immutable Map.", "2.13.0")
354-
@`inline` def -- (keys: IterableOnce[K]): C = {
354+
@`inline` def -- (keys: IterableOnce[K]^): C = {
355355
lazy val keysSet = keys.iterator.to(immutable.Set)
356356
fromSpecific(this.view.filterKeys(k => !keysSet.contains(k)))
357357
}
358358

359359
@deprecated("Use ++ instead of ++: for collections of type Iterable", "2.13.0")
360-
def ++: [V1 >: V](that: IterableOnce[(K,V1)]): CC[K,V1] = {
361-
val thatIterable: Iterable[(K, V1)] = that match {
360+
def ++: [V1 >: V](that: IterableOnce[(K,V1)]^): CC[K,V1] = {
361+
val thatIterable: Iterable[(K, V1)]^{that} = that match {
362362
case that: Iterable[(K, V1)] => that
363363
case that => View.from(that)
364364
}
@@ -381,10 +381,10 @@ object MapOps {
381381
def map[K2, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] =
382382
self.mapFactory.from(new View.Map(filtered, f))
383383

384-
def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] =
384+
def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)]^): CC[K2, V2] =
385385
self.mapFactory.from(new View.FlatMap(filtered, f))
386386

387-
override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, CC] =
387+
override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, CC]^{p, q} =
388388
new WithFilter[K, V, IterableCC, CC](self, (kv: (K, V)) => p(kv) && q(kv))
389389

390390
}

0 commit comments

Comments
 (0)