diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2015-10-02 23:25:30 +0200 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2015-10-09 15:00:08 +0200 |
commit | 82a6d6f52065ae39a0a162f95e5002a6ab26cc55 (patch) | |
tree | f9a3667539ccc93d1aabc1031c60ed5575b32fde /src/dotty/tools/dotc/typer/TypeAssigner.scala | |
parent | d1014c3a2cf87b783f383e52b8923a42ee1bc31c (diff) | |
download | dotty-82a6d6f52065ae39a0a162f95e5002a6ab26cc55.tar.gz dotty-82a6d6f52065ae39a0a162f95e5002a6ab26cc55.tar.bz2 dotty-82a6d6f52065ae39a0a162f95e5002a6ab26cc55.zip |
TypeAssigner#avoid: do not lose type parameters when the base type changes.
Fixes #741.
Diffstat (limited to 'src/dotty/tools/dotc/typer/TypeAssigner.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 22c062243..7225ede14 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -87,13 +87,28 @@ trait TypeAssigner { case _ => mapOver(tp) } - case tp: RefinedType => - val tp1 @ RefinedType(parent1, _) = mapOver(tp) - if (toAvoid(tp1.refinedInfo) && variance > 0) { - typr.println(s"dropping refinement from $tp1") - parent1 + case tp @ RefinedType(parent, name) if variance > 0 => + // The naive approach here would be to first approximate the parent, + // but if the base type of the approximated parent is different from + // the current base type, then the current refinement won't be valid + // if it's a type parameter refinement. + // Therefore we first approximate the base type, then use `baseArgInfos` + // to get correct refinements for the approximated base type, then + // recursively approximate the resulting type. + val base = tp.unrefine + if (toAvoid(base)) { + val base1 = apply(base) + apply(base1.appliedTo(tp.baseArgInfos(base1.typeSymbol))) + } else { + val parent1 = apply(tp.parent) + val refinedInfo1 = apply(tp.refinedInfo) + if (toAvoid(refinedInfo1)) { + typr.println(s"dropping refinement from $tp") + parent1 + } else { + tp.derivedRefinedType(parent1, name, refinedInfo1) + } } - else tp1 case tp: TypeVar if ctx.typerState.constraint.contains(tp) => val lo = ctx.typerState.constraint.fullLowerBound(tp.origin) val lo1 = avoid(lo, symsToAvoid) |