Skip to content

Commit 82a6d6f

Browse files
committed
TypeAssigner#avoid: do not lose type parameters when the base type changes.
Fixes #741.
1 parent d1014c3 commit 82a6d6f

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,28 @@ trait TypeAssigner {
8787
case _ =>
8888
mapOver(tp)
8989
}
90-
case tp: RefinedType =>
91-
val tp1 @ RefinedType(parent1, _) = mapOver(tp)
92-
if (toAvoid(tp1.refinedInfo) && variance > 0) {
93-
typr.println(s"dropping refinement from $tp1")
94-
parent1
90+
case tp @ RefinedType(parent, name) if variance > 0 =>
91+
// The naive approach here would be to first approximate the parent,
92+
// but if the base type of the approximated parent is different from
93+
// the current base type, then the current refinement won't be valid
94+
// if it's a type parameter refinement.
95+
// Therefore we first approximate the base type, then use `baseArgInfos`
96+
// to get correct refinements for the approximated base type, then
97+
// recursively approximate the resulting type.
98+
val base = tp.unrefine
99+
if (toAvoid(base)) {
100+
val base1 = apply(base)
101+
apply(base1.appliedTo(tp.baseArgInfos(base1.typeSymbol)))
102+
} else {
103+
val parent1 = apply(tp.parent)
104+
val refinedInfo1 = apply(tp.refinedInfo)
105+
if (toAvoid(refinedInfo1)) {
106+
typr.println(s"dropping refinement from $tp")
107+
parent1
108+
} else {
109+
tp.derivedRefinedType(parent1, name, refinedInfo1)
110+
}
95111
}
96-
else tp1
97112
case tp: TypeVar if ctx.typerState.constraint.contains(tp) =>
98113
val lo = ctx.typerState.constraint.fullLowerBound(tp.origin)
99114
val lo1 = avoid(lo, symsToAvoid)

tests/pos/escapingRefs.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ class Outer {
66

77
class HasA { type A }
88

9+
class Foo[A]
10+
911
object Test {
1012
def test = {
1113
val a: Outer#Inner = {
@@ -26,5 +28,15 @@ object Test {
2628
val x: HasA { type A = h.A } = h
2729
x
2830
}
31+
32+
val d: Foo[Int] = {
33+
class Bar[B] extends Foo[B]
34+
new Bar[Int]
35+
}
36+
37+
val e: Foo[_] = {
38+
class Bar[B] extends Foo[B]
39+
new Bar[Int]: Bar[_ <: Int]
40+
}
2941
}
3042
}

0 commit comments

Comments
 (0)