Skip to content

Commit 48acd08

Browse files
committed
TypeAssigner#avoid: more precise types for inner classes
When we need to avoid `A` in the class `A#B`, we can try to replace `A` by a supertype. Previously, we only tried to replace `A#B` itself by a supertype. Fixes #711.
1 parent 5f7e290 commit 48acd08

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ trait TypeAssigner {
3131
/** An upper approximation of the given type `tp` that does not refer to any symbol in `symsToAvoid`.
3232
* Approximation steps are:
3333
*
34-
* - follow aliases if the original refers to a forbidden symbol
34+
* - follow aliases and upper bounds if the original refers to a forbidden symbol
3535
* - widen termrefs that refer to a forbidden symbol
3636
* - replace ClassInfos of forbidden classes by the intersection of their parents, refined by all
3737
* non-private fields, methods, and type members.
38+
* - if the prefix of a class refers to a forbidden symbol, first try to replace the prefix,
39+
* if this is not possible, replace the ClassInfo as above.
3840
* - drop refinements referring to a forbidden symbol.
3941
*/
4042
def avoid(tp: Type, symsToAvoid: => List[Symbol])(implicit ctx: Context): Type = {
@@ -52,14 +54,20 @@ trait TypeAssigner {
5254
case _ =>
5355
false
5456
}
55-
def apply(tp: Type) = tp match {
57+
def apply(tp: Type): Type = tp match {
5658
case tp: TermRef if toAvoid(tp) && variance > 0 =>
5759
apply(tp.info.widenExpr)
5860
case tp: TypeRef if (forbidden contains tp.symbol) || toAvoid(tp.prefix) =>
5961
tp.info match {
6062
case TypeAlias(ref) =>
6163
apply(ref)
6264
case info: ClassInfo if variance > 0 =>
65+
if (!(forbidden contains tp.symbol)) {
66+
val prefix = apply(tp.prefix)
67+
val tp1 = tp.derivedSelect(prefix)
68+
if (tp1.typeSymbol.exists)
69+
return tp1
70+
}
6371
val parentType = info.instantiatedParents.reduceLeft(ctx.typeComparer.andType(_, _))
6472
def addRefinement(parent: Type, decl: Symbol) = {
6573
val inherited =

tests/pos/escapingRefs.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Outer {
2+
class Inner
3+
}
4+
5+
object Test {
6+
def test = {
7+
val a: Outer#Inner = {
8+
val o = new Outer
9+
new o.Inner
10+
}
11+
}
12+
}

0 commit comments

Comments
 (0)