Skip to content

Commit 8ad4602

Browse files
committed
Fix #5844: Sanitize base type before substituting wildcard arguments
1 parent 7ff971f commit 8ad4602

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,40 @@ object SymDenotations {
17271727
baseTp
17281728
}
17291729

1730+
/** Sanitize base type so that wildvard arguments can be safely handled by
1731+
* substitution. If base type is of the form `B[S_1, ..., S_n]`, then
1732+
* for every `S_i:
1733+
* for every wildcard argument args_j in `args`:
1734+
* if the corresponding parameter `tparam_j` is referenced by `S_i`,
1735+
* but `S_i != tparam_j`, then
1736+
* replace S_i with `_`.
1737+
*
1738+
* This prevents a non-sensical substitution of `tparam_j` in `S_i` by a wildcard
1739+
* type (of class TypeBounds). See pos/i5844.scala as a test case.
1740+
*/
1741+
def handleWildcards(base: Type, tparams: List[Symbol], args: List[Type]): Type = {
1742+
def sanitize(baseArg: Type, tparams: List[Symbol], args: List[Type]): Type = args match {
1743+
case arg :: args1 =>
1744+
val tparam :: tparams1 = tparams
1745+
val pref = tparam.typeRef
1746+
val baseArg1 = arg match {
1747+
case arg: TypeBounds if baseArg != pref && pref.occursIn(baseArg) =>
1748+
TypeBounds.empty
1749+
case _ =>
1750+
baseArg
1751+
}
1752+
sanitize(baseArg1, tparams1, args1)
1753+
case nil =>
1754+
baseArg
1755+
}
1756+
base match {
1757+
case base @ AppliedType(tycon, baseArgs) =>
1758+
base.derivedAppliedType(tycon, baseArgs.mapconserve(sanitize(_, tparams, args)))
1759+
case _ =>
1760+
base
1761+
}
1762+
}
1763+
17301764
def recur(tp: Type): Type = try {
17311765
tp match {
17321766
case tp: CachedType =>
@@ -1790,7 +1824,10 @@ object SymDenotations {
17901824
case LambdaParam(_, _) :: _ =>
17911825
recur(tp.superType)
17921826
case tparams: List[Symbol @unchecked] =>
1793-
recur(tycon).subst(tparams, args)
1827+
var base = recur(tycon)
1828+
if (args.exists(_.isInstanceOf[TypeBounds]))
1829+
base = handleWildcards(base, tparams, args)
1830+
base.subst(tparams, args)
17941831
}
17951832
record(tp, baseTp)
17961833
baseTp

tests/pos/i5844.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
trait A
2+
trait B[X, Y]{
3+
def m(): X
4+
}
5+
trait C[X] extends B[X, X & A]
6+
7+
object O{
8+
def m(c: C[_]) = {
9+
val x = c.m()
10+
}
11+
}

0 commit comments

Comments
 (0)