Skip to content

Commit 827dc26

Browse files
committed
Fix derivedSelect in avoid
Test case in i2945.scala.
1 parent de19138 commit 827dc26

File tree

3 files changed

+51
-18
lines changed

3 files changed

+51
-18
lines changed

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

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3892,14 +3892,14 @@ object Types {
38923892
case _ => tp
38933893
}
38943894

3895-
/** Derived selection.
3896-
* @pre the (upper bound of) prefix `pre` has a member named `tp.name`.
3895+
/** Try to widen a named type to its info relative to given prefix `pre`, where possible.
3896+
* The possible cases are listed inline in the code. Return `default` if no widening is
3897+
* possible.
38973898
*/
3898-
override protected def derivedSelect(tp: NamedType, pre: Type) =
3899-
if (pre eq tp.prefix) tp
3900-
else pre match {
3901-
case Range(preLo, preHi) =>
3902-
preHi.member(tp.name).info.widenExpr match {
3899+
def tryWiden(tp: NamedType, pre: Type)(default: => Type): Type =
3900+
pre.member(tp.name) match {
3901+
case d: SingleDenotation =>
3902+
d.info match {
39033903
case TypeAlias(alias) =>
39043904
// if H#T = U, then for any x in L..H, x.T =:= U,
39053905
// hence we can replace with U under all variances
@@ -3913,9 +3913,21 @@ object Types {
39133913
// hence we can replace with y.type under all variances
39143914
reapply(info)
39153915
case _ =>
3916-
range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
3916+
default
39173917
}
3918-
case _ => tp.derivedSelect(pre)
3918+
case _ => default
3919+
}
3920+
3921+
/** Derived selection.
3922+
* @pre the (upper bound of) prefix `pre` has a member named `tp.name`.
3923+
*/
3924+
override protected def derivedSelect(tp: NamedType, pre: Type) =
3925+
if (pre eq tp.prefix) tp
3926+
else pre match {
3927+
case Range(preLo, preHi) =>
3928+
tryWiden(tp, preHi)(range(tp.derivedSelect(preLo), tp.derivedSelect(preHi)))
3929+
case _ =>
3930+
tp.derivedSelect(pre)
39193931
}
39203932

39213933
override protected def derivedRefinedType(tp: RefinedType, parent: Type, info: Type) =

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,26 @@ trait TypeAssigner {
108108
mapOver(tp)
109109
}
110110

111-
/** Two deviations from standard derivedSelect:
112-
* 1. The teh approximation result is a singleton references C#x.type, we
111+
/** Three deviations from standard derivedSelect:
112+
* 1. We first try a widening conversion to the type's info with
113+
* the original prefix. Since the original prefix is known to
114+
* be a subtype of the returned prefix, this can improve results.
115+
* 2. IThen, if the approximation result is a singleton reference C#x.type, we
113116
* replace by the widened type, which is usually more natural.
114-
* 2. We need to handle the case where the prefix type does not have a member
115-
* named `tp.name` anymmore.
117+
* 3. Finally, we need to handle the case where the prefix type does not have a member
118+
* named `tp.name` anymmore. In that case, we need to fall back to Bot..Top.
116119
*/
117120
override def derivedSelect(tp: NamedType, pre: Type) =
118-
if (pre eq tp.prefix) tp
119-
else if (tp.isTerm && variance > 0 && !pre.isInstanceOf[SingletonType])
120-
apply(tp.info.widenExpr)
121-
else if (upper(pre).member(tp.name).exists) super.derivedSelect(tp, pre)
122-
else range(tp.bottomType, tp.topType)
121+
if (pre eq tp.prefix)
122+
tp
123+
else tryWiden(tp, tp.prefix) {
124+
if (tp.isTerm && variance > 0 && !pre.isInstanceOf[SingletonType])
125+
apply(tp.info.widenExpr)
126+
else if (upper(pre).member(tp.name).exists)
127+
super.derivedSelect(tp, pre)
128+
else
129+
range(tp.bottomType, tp.topType)
130+
}
123131
}
124132

125133
widenMap(tp)

tests/pos/i2945.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Test {
2+
def test = {
3+
object Hi {
4+
type A = Int
5+
}
6+
7+
val x: Hi.A = 1
8+
9+
List(x)
10+
}
11+
12+
val hi: List[Int] = test // Used to fail because `test` had type `List[Any]` instead of `List[Int]`
13+
}

0 commit comments

Comments
 (0)