Skip to content

Commit 153b958

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 72bab91 commit 153b958

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
@@ -1631,17 +1631,19 @@ object Types extends TypeUtils {
16311631
*
16321632
* P { ... type T = / += / -= U ... } # T
16331633
*
1634-
* to just U. Does not perform the reduction if the resulting type would contain
1635-
* a reference to the "this" of the current refined type, except in the following situation
1634+
* to just U. Analogously, `P { val x: S} # x` is reduced tp `S` is `S`
1635+
* is a singleton type.
16361636
*
1637-
* (1) The "this" reference can be avoided by following an alias. Example:
1637+
* Does not perform the reduction if the resulting type would contain
1638+
* a reference to the "this" of the current refined type, except if the "this"
1639+
* reference can be avoided by following an alias. Example:
16381640
*
16391641
* P { type T = String, type R = P{...}.T } # R --> String
16401642
*
16411643
* (*) normalizes means: follow instantiated typevars and aliases.
16421644
*/
1643-
def lookupRefined(name: Name)(using Context): Type = {
1644-
@tailrec def loop(pre: Type): Type = pre.stripTypeVar match {
1645+
def lookupRefined(name: Name)(using Context): Type =
1646+
@tailrec def loop(pre: Type): Type = pre match
16451647
case pre: RefinedType =>
16461648
pre.refinedInfo match {
16471649
case tp: AliasingBounds =>
@@ -1664,12 +1666,13 @@ object Types extends TypeUtils {
16641666
case TypeAlias(alias) => loop(alias)
16651667
case _ => NoType
16661668
}
1669+
case pre: (TypeVar | AnnotatedType) =>
1670+
loop(pre.underlying)
16671671
case _ =>
16681672
NoType
1669-
}
16701673

16711674
loop(this)
1672-
}
1675+
end lookupRefined
16731676

16741677
/** The type <this . name> , reduced if possible */
16751678
def select(name: Name)(using Context): Type =
@@ -2809,35 +2812,30 @@ object Types extends TypeUtils {
28092812
def derivedSelect(prefix: Type)(using Context): Type =
28102813
if prefix eq this.prefix then this
28112814
else if prefix.isExactlyNothing then prefix
2812-
else {
2813-
val res =
2814-
if (isType && currentValidSymbol.isAllOf(ClassTypeParam)) argForParam(prefix)
2815+
else
2816+
val reduced =
2817+
if isType && currentValidSymbol.isAllOf(ClassTypeParam) then argForParam(prefix)
28152818
else prefix.lookupRefined(name)
2816-
if (res.exists) return res
2817-
if (isType) {
2818-
if (Config.splitProjections)
2819-
prefix match {
2820-
case prefix: AndType =>
2821-
def isMissing(tp: Type) = tp match {
2822-
case tp: TypeRef => !tp.info.exists
2823-
case _ => false
2824-
}
2825-
val derived1 = derivedSelect(prefix.tp1)
2826-
val derived2 = derivedSelect(prefix.tp2)
2827-
return (
2828-
if (isMissing(derived1)) derived2
2829-
else if (isMissing(derived2)) derived1
2830-
else prefix.derivedAndType(derived1, derived2))
2831-
case prefix: OrType =>
2832-
val derived1 = derivedSelect(prefix.tp1)
2833-
val derived2 = derivedSelect(prefix.tp2)
2834-
return prefix.derivedOrType(derived1, derived2)
2835-
case _ =>
2836-
}
2837-
}
2838-
if (prefix.isInstanceOf[WildcardType]) WildcardType.sameKindAs(this)
2819+
if reduced.exists then return reduced
2820+
if Config.splitProjections && isType then
2821+
prefix match
2822+
case prefix: AndType =>
2823+
def isMissing(tp: Type) = tp match
2824+
case tp: TypeRef => !tp.info.exists
2825+
case _ => false
2826+
val derived1 = derivedSelect(prefix.tp1)
2827+
val derived2 = derivedSelect(prefix.tp2)
2828+
return
2829+
if isMissing(derived1) then derived2
2830+
else if isMissing(derived2) then derived1
2831+
else prefix.derivedAndType(derived1, derived2)
2832+
case prefix: OrType =>
2833+
val derived1 = derivedSelect(prefix.tp1)
2834+
val derived2 = derivedSelect(prefix.tp2)
2835+
return prefix.derivedOrType(derived1, derived2)
2836+
case _ =>
2837+
if prefix.isInstanceOf[WildcardType] then WildcardType.sameKindAs(this)
28392838
else withPrefix(prefix)
2840-
}
28412839

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

0 commit comments

Comments
 (0)