Skip to content

Commit 48e5438

Browse files
committed
Also reduce term projections
We already reduce `R { type A = T } # A` to `T` in most situations when we create types. We now also reduce `R { val x: S } # x` to `S` if `S` is a singleton type. This will simplify types as we go to more term-dependent typing. As a concrete benefit, it will avoid several test-pickling failures due to pickling differences when using dependent types.
1 parent 1153b16 commit 48e5438

File tree

1 file changed

+32
-34
lines changed

1 file changed

+32
-34
lines changed

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

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,17 +1641,19 @@ object Types extends TypeUtils {
16411641
*
16421642
* P { ... type T = / += / -= U ... } # T
16431643
*
1644-
* to just U. Does not perform the reduction if the resulting type would contain
1645-
* a reference to the "this" of the current refined type, except in the following situation
1644+
* to just U. Analogously, `P { val x: S} # x` is reduced tp `S` is `S`
1645+
* is a singleton type.
16461646
*
1647-
* (1) The "this" reference can be avoided by following an alias. Example:
1647+
* Does not perform the reduction if the resulting type would contain
1648+
* a reference to the "this" of the current refined type, except if the "this"
1649+
* reference can be avoided by following an alias. Example:
16481650
*
16491651
* P { type T = String, type R = P{...}.T } # R --> String
16501652
*
16511653
* (*) normalizes means: follow instantiated typevars and aliases.
16521654
*/
1653-
def lookupRefined(name: Name)(using Context): Type = {
1654-
@tailrec def loop(pre: Type): Type = pre.stripTypeVar match {
1655+
def lookupRefined(name: Name)(using Context): Type =
1656+
@tailrec def loop(pre: Type): Type = pre match
16551657
case pre: RefinedType =>
16561658
pre.refinedInfo match {
16571659
case tp: AliasingBounds =>
@@ -1674,12 +1676,13 @@ object Types extends TypeUtils {
16741676
case TypeAlias(alias) => loop(alias)
16751677
case _ => NoType
16761678
}
1679+
case pre: (TypeVar | AnnotatedType) =>
1680+
loop(pre.underlying)
16771681
case _ =>
16781682
NoType
1679-
}
16801683

16811684
loop(this)
1682-
}
1685+
end lookupRefined
16831686

16841687
/** The type <this . name> , reduced if possible */
16851688
def select(name: Name)(using Context): Type =
@@ -2819,35 +2822,30 @@ object Types extends TypeUtils {
28192822
def derivedSelect(prefix: Type)(using Context): Type =
28202823
if prefix eq this.prefix then this
28212824
else if prefix.isExactlyNothing then prefix
2822-
else {
2823-
val res =
2824-
if (isType && currentValidSymbol.isAllOf(ClassTypeParam)) argForParam(prefix)
2825+
else
2826+
val reduced =
2827+
if isType && currentValidSymbol.isAllOf(ClassTypeParam) then argForParam(prefix)
28252828
else prefix.lookupRefined(name)
2826-
if (res.exists) return res
2827-
if (isType) {
2828-
if (Config.splitProjections)
2829-
prefix match {
2830-
case prefix: AndType =>
2831-
def isMissing(tp: Type) = tp match {
2832-
case tp: TypeRef => !tp.info.exists
2833-
case _ => false
2834-
}
2835-
val derived1 = derivedSelect(prefix.tp1)
2836-
val derived2 = derivedSelect(prefix.tp2)
2837-
return (
2838-
if (isMissing(derived1)) derived2
2839-
else if (isMissing(derived2)) derived1
2840-
else prefix.derivedAndType(derived1, derived2))
2841-
case prefix: OrType =>
2842-
val derived1 = derivedSelect(prefix.tp1)
2843-
val derived2 = derivedSelect(prefix.tp2)
2844-
return prefix.derivedOrType(derived1, derived2)
2845-
case _ =>
2846-
}
2847-
}
2848-
if (prefix.isInstanceOf[WildcardType]) WildcardType.sameKindAs(this)
2829+
if reduced.exists then return reduced
2830+
if Config.splitProjections && isType then
2831+
prefix match
2832+
case prefix: AndType =>
2833+
def isMissing(tp: Type) = tp match
2834+
case tp: TypeRef => !tp.info.exists
2835+
case _ => false
2836+
val derived1 = derivedSelect(prefix.tp1)
2837+
val derived2 = derivedSelect(prefix.tp2)
2838+
return
2839+
if isMissing(derived1) then derived2
2840+
else if isMissing(derived2) then derived1
2841+
else prefix.derivedAndType(derived1, derived2)
2842+
case prefix: OrType =>
2843+
val derived1 = derivedSelect(prefix.tp1)
2844+
val derived2 = derivedSelect(prefix.tp2)
2845+
return prefix.derivedOrType(derived1, derived2)
2846+
case _ =>
2847+
if prefix.isInstanceOf[WildcardType] then WildcardType.sameKindAs(this)
28492848
else withPrefix(prefix)
2850-
}
28512849

28522850
/** A reference like this one, but with the given symbol, if it exists */
28532851
private def withSym(sym: Symbol)(using Context): ThisType =

0 commit comments

Comments
 (0)