@@ -1727,6 +1727,58 @@ object SymDenotations {
1727
1727
baseTp
1728
1728
}
1729
1729
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
+ * and the reference does not itself appear in argument position, 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 problemRef = new TypeAccumulator [Boolean ] {
1746
+ // Does `tp` contain a reference to `tparam` that does not appear itself
1747
+ // in argument position of an AppliedType with a class constructor?
1748
+ def apply (x : Boolean , tp : Type ): Boolean =
1749
+ x || {
1750
+ tp match {
1751
+ case tp @ TypeRef (prefix, _) =>
1752
+ tp.symbol == tparam || apply(x, prefix)
1753
+ case AppliedType (tycon, args) if tycon.typeSymbol.isClass =>
1754
+ apply(x, tycon) || args.exists(foldOver(x, _))
1755
+ case _ =>
1756
+ foldOver(x, tp)
1757
+ }
1758
+ }
1759
+ }
1760
+ def isParamRef (tp : Type ) = tp match {
1761
+ case tp : TypeRef => tp.symbol == tparam
1762
+ case _ => false
1763
+ }
1764
+ val baseArg1 = arg match {
1765
+ case arg : TypeBounds if ! isParamRef(baseArg) && problemRef(false , baseArg) =>
1766
+ TypeBounds .empty
1767
+ case _ =>
1768
+ baseArg
1769
+ }
1770
+ sanitize(baseArg1, tparams1, args1)
1771
+ case nil =>
1772
+ baseArg
1773
+ }
1774
+ base match {
1775
+ case base @ AppliedType (tycon, baseArgs) =>
1776
+ base.derivedAppliedType(tycon, baseArgs.mapconserve(sanitize(_, tparams, args)))
1777
+ case _ =>
1778
+ base
1779
+ }
1780
+ }
1781
+
1730
1782
def recur (tp : Type ): Type = try {
1731
1783
tp match {
1732
1784
case tp : CachedType =>
@@ -1790,7 +1842,10 @@ object SymDenotations {
1790
1842
case LambdaParam (_, _) :: _ =>
1791
1843
recur(tp.superType)
1792
1844
case tparams : List [Symbol @ unchecked] =>
1793
- recur(tycon).subst(tparams, args)
1845
+ var base = recur(tycon)
1846
+ if (args.exists(_.isInstanceOf [TypeBounds ]))
1847
+ base = handleWildcards(base, tparams, args)
1848
+ base.subst(tparams, args)
1794
1849
}
1795
1850
record(tp, baseTp)
1796
1851
baseTp
0 commit comments