Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c8d77df

Browse files
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)

AltStyle によって変換されたページ (->オリジナル) /