Skip to content

Commit c8d77df

Browse files
authored
Revert "Revert "Disable distribution of intersection types over applied types"" (#23923)
Reverts #23920
2 parents f9f48a8 + 4d2442b commit c8d77df

35 files changed

+217
-104
lines changed

compiler/src/dotty/tools/dotc/config/SourceVersion.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ enum SourceVersion:
4444
def enablesNewGivens = isAtLeast(`3.6`)
4545
def enablesNamedTuples = isAtLeast(`3.7`)
4646
def enablesBetterFors(using Context) = isAtLeast(`3.8`) || (isAtLeast(`3.7`) && isPreviewEnabled)
47+
/** See PR #23441 and tests/neg/i23435-min */
48+
def enablesDistributeAnd = !isAtLeast(`3.8`)
4749

4850
def requiresNewSyntax = isAtLeast(future)
4951

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ class Definitions {
460460
@tu lazy val CBCompanion: TypeSymbol = // type `<context-bound-companion>`[-Refs]
461461
enterPermanentSymbol(tpnme.CBCompanion,
462462
TypeBounds(NothingType,
463-
HKTypeLambda(tpnme.syntheticTypeParamName(0) :: Nil, Contravariant :: Nil)(
463+
HKTypeLambda(tpnme.syntheticTypeParamName(0) :: Nil)(
464464
tl => TypeBounds.empty :: Nil,
465465
tl => AnyType))).asType
466466

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ object NamerOps:
307307
* The context-bound companion has as name the name of `tsym` translated to
308308
* a term name. We create a synthetic val of the form
309309
*
310-
* val A: `<context-bound-companion>`[witnessRef1 | ... | witnessRefN]
310+
* val A: `<context-bound-companion>`[witnessRef1] & ... & `<context-bound-companion>`[witnessRefN]
311311
*
312312
* where
313313
*
@@ -325,8 +325,7 @@ object NamerOps:
325325
prefix.select(params.find(_.name == witnessName).get)
326326
else
327327
witnessNames.map(TermRef(prefix, _))
328-
val cbtype = defn.CBCompanion.typeRef.appliedTo:
329-
witnessRefs.reduce[Type](OrType(_, _, soft = false))
328+
val cbtype = witnessRefs.map(defn.CBCompanion.typeRef.appliedTo).reduce(AndType.apply)
330329
val cbc = newSymbol(
331330
ctx.owner, companionName,
332331
(tsym.flagsUNSAFE & (AccessFlags)).toTermFlags | Synthetic,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class SymUtils:
8888
}
8989

9090
def isContextBoundCompanion(using Context): Boolean =
91-
self.is(Synthetic) && self.infoOrCompleter.typeSymbol == defn.CBCompanion
91+
self.is(Synthetic) && self.infoOrCompleter.isContextBoundCompanion
9292

9393
def isDummyCaptureParam(using Context): Boolean =
9494
self.is(PhantomSymbol) && self.infoOrCompleter.typeSymbol != defn.CBCompanion

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Symbols.*
88
import SymDenotations.LazyType
99
import Decorators.*
1010
import util.Stats.*
11+
import config.Feature.sourceVersion
1112
import Names.*
1213
import StdNames.nme
1314
import Flags.{Module, Provisional}
@@ -475,13 +476,20 @@ class TypeApplications(val self: Type) extends AnyVal {
475476
self.derivedExprType(tp.translateParameterized(from, to))
476477
case _ =>
477478
if (self.derivesFrom(from)) {
479+
// NOTE: we assume the `To` class is covariant s.t.
480+
// `To[T] X To[U] <:< To[T | U]` where X ::= `&` | `|`
478481
def elemType(tp: Type): Type = tp.widenDealias match
479482
case tp: OrType =>
480483
if tp.tp1.isBottomType then elemType(tp.tp2)
481484
else if tp.tp2.isBottomType then elemType(tp.tp1)
482485
else tp.derivedOrType(elemType(tp.tp1), elemType(tp.tp2))
483-
case tp: AndType => tp.derivedAndType(elemType(tp.tp1), elemType(tp.tp2))
484-
case _ => tp.baseType(from).argInfos.headOption.getOrElse(defn.NothingType)
486+
case tp @ AndType(tp1, tp2) =>
487+
if sourceVersion.enablesDistributeAnd
488+
then tp.derivedAndType(elemType(tp1), elemType(tp2))
489+
else OrType(elemType(tp1), elemType(tp2), soft = false)
490+
case _ =>
491+
tp.baseType(from).argInfos.headOption.getOrElse(defn.NothingType)
492+
end elemType
485493
val arg = elemType(self)
486494
val arg1 = if (wildcardArg) TypeBounds.upper(arg) else arg
487495
to.typeRef.appliedTo(arg1)

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,7 +2460,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
24602460

24612461
/** If the range `tp1..tp2` consist of a single type, that type, otherwise NoType`.
24622462
* This is the case if `tp1 =:= tp2`, but also if `tp1 <:< tp2`, `tp1` is a singleton type,
2463-
* and `tp2` derives from `scala.Singleton` (or vice-versa). Examples of the latter case:
2463+
* and `tp2` derives from `scala.Singleton` and `sourceVersion.enablesDistributeAnd` (or vice-versa).
2464+
* Examples of the latter case:
24642465
*
24652466
* "name".type .. Singleton
24662467
* "name".type .. String & Singleton
@@ -2473,8 +2474,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
24732474
def isSingletonBounds(lo: Type, hi: Type) =
24742475
lo.isSingleton && hi.derivesFrom(defn.SingletonClass) && isSubTypeWhenFrozen(lo, hi)
24752476
if (isSameTypeWhenFrozen(tp1, tp2)) tp1
2476-
else if (isSingletonBounds(tp1, tp2)) tp1
2477-
else if (isSingletonBounds(tp2, tp1)) tp2
2477+
else if sourceVersion.enablesDistributeAnd then
2478+
if (isSingletonBounds(tp1, tp2)) tp1
2479+
else if (isSingletonBounds(tp2, tp1)) tp2
2480+
else NoType
24782481
else NoType
24792482
}
24802483

@@ -2771,7 +2774,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
27712774
* @pre !(tp1 <: tp2) && !(tp2 <:< tp1) -- these cases were handled before
27722775
*/
27732776
private def distributeAnd(tp1: Type, tp2: Type): Type = tp1 match {
2774-
case tp1 @ AppliedType(tycon1, args1) =>
2777+
case tp1 @ AppliedType(tycon1, args1) if sourceVersion.enablesDistributeAnd =>
27752778
tp2 match {
27762779
case AppliedType(tycon2, args2)
27772780
if tycon1.typeSymbol == tycon2.typeSymbol && tycon1 =:= tycon2 =>
@@ -2819,8 +2822,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
28192822
}
28202823

28212824
/** Try to distribute `|` inside type, detect and handle conflicts
2822-
* Note that, unlike for `&`, a disjunction cannot be pushed into
2823-
* a refined or applied type. Example:
2825+
* Note that a disjunction cannot be pushed into a refined or applied type. Example:
28242826
*
28252827
* List[T] | List[U] is not the same as List[T | U].
28262828
*

0 commit comments

Comments
 (0)