Skip to content

Commit d6dfcc3

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

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
@@ -83,13 +83,28 @@ trait TypeAssigner {
8383
case _ =>
8484
mapOver(tp)
8585
}
86-
case tp: RefinedType =>
87-
val tp1 @ RefinedType(parent1, _) = mapOver(tp)
88-
if (toAvoid(tp1.refinedInfo) && variance > 0) {
89-
typr.println(s"dropping refinement from $tp1")
90-
parent1
86+
case tp @ RefinedType(parent, name) if variance > 0 =>
87+
// The naive approach here would be to first approximate the parent,
88+
// but if the base type of the approximated parent is different from
89+
// the current base type, then the current refinement won't be valid
90+
// if it's a type parameter refinement.
91+
// Therefore we first approximate the base type, then use `baseArgInfos`
92+
// to get correct refinements for the approximated base type, then
93+
// recursively approximate the resulting type.
94+
val base = tp.unrefine
95+
if (toAvoid(base)) {
96+
val base1 = apply(base)
97+
apply(base1.appliedTo(tp.baseArgInfos(base1.typeSymbol)))
98+
} else {
99+
val parent1 = apply(tp.parent)
100+
val refinedInfo1 = apply(tp.refinedInfo)
101+
if (toAvoid(refinedInfo1)) {
102+
typr.println(s"dropping refinement from $tp")
103+
parent1
104+
} else {
105+
tp.derivedRefinedType(parent1, name, refinedInfo1)
106+
}
91107
}
92-
else tp1
93108
case tp: TypeVar if ctx.typerState.constraint.contains(tp) =>
94109
val lo = ctx.typerState.constraint.fullLowerBound(tp.origin)
95110
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)