Skip to content

Commit 96fbf29

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 11d7fa3 commit 96fbf29

File tree

1 file changed

+32
-34
lines changed

1 file changed

+32
-34
lines changed

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

+32-34
Original file line numberDiff line numberDiff line change
@@ -1642,17 +1642,19 @@ object Types extends TypeUtils {
16421642
*
16431643
* P { ... type T = / += / -= U ... } # T
16441644
*
1645-
* to just U. Does not perform the reduction if the resulting type would contain
1646-
* a reference to the "this" of the current refined type, except in the following situation
1645+
* to just U. Analogously, `P { val x: S} # x` is reduced tp `S` is `S`
1646+
* is a singleton type.
16471647
*
1648-
* (1) The "this" reference can be avoided by following an alias. Example:
1648+
* Does not perform the reduction if the resulting type would contain
1649+
* a reference to the "this" of the current refined type, except if the "this"
1650+
* reference can be avoided by following an alias. Example:
16491651
*
16501652
* P { type T = String, type R = P{...}.T } # R --> String
16511653
*
16521654
* (*) normalizes means: follow instantiated typevars and aliases.
16531655
*/
1654-
def lookupRefined(name: Name)(using Context): Type = {
1655-
@tailrec def loop(pre: Type): Type = pre.stripTypeVar match {
1656+
def lookupRefined(name: Name)(using Context): Type =
1657+
@tailrec def loop(pre: Type): Type = pre match
16561658
case pre: RefinedType =>
16571659
pre.refinedInfo match {
16581660
case tp: AliasingBounds =>
@@ -1675,12 +1677,13 @@ object Types extends TypeUtils {
16751677
case TypeAlias(alias) => loop(alias)
16761678
case _ => NoType
16771679
}
1680+
case pre: (TypeVar | AnnotatedType) =>
1681+
loop(pre.underlying)
16781682
case _ =>
16791683
NoType
1680-
}
16811684

16821685
loop(this)
1683-
}
1686+
end lookupRefined
16841687

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

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

0 commit comments

Comments
 (0)