diff --git a/compiler/src/dotty/tools/dotc/core/Substituters.scala b/compiler/src/dotty/tools/dotc/core/Substituters.scala index ab07a4d568fd..f39ec9a33913 100644 --- a/compiler/src/dotty/tools/dotc/core/Substituters.scala +++ b/compiler/src/dotty/tools/dotc/core/Substituters.scala @@ -195,4 +195,28 @@ trait Substituters { this: Context => final class SubstParamsMap(from: BindingType, to: List[Type]) extends DeepTypeMap { def apply(tp: Type): Type = substParams(tp, from, to, this) } + + /** An approximating substitution that can handle wildcards in the `to` list */ + final class SubstApproxMap(from: List[Symbol], to: List[Type])(implicit ctx: Context) extends ApproximatingTypeMap { + def apply(tp: Type): Type = tp match { + case tp: NamedType => + val sym = tp.symbol + var fs = from + var ts = to + while (fs.nonEmpty) { + if (fs.head eq sym) + return ts.head match { + case TypeBounds(lo, hi) => range(lo, hi) + case tp1 => tp1 + } + fs = fs.tail + ts = ts.tail + } + if (tp.prefix `eq` NoPrefix) tp else derivedSelect(tp, apply(tp.prefix)) + case _: ThisType | _: BoundType => + tp + case _ => + mapOver(tp) + } + } } diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 14dfa73b1a1a..93b04c5bda3e 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1790,7 +1790,7 @@ object SymDenotations { case LambdaParam(_, _) :: _ => recur(tp.superType) case tparams: List[Symbol @unchecked] => - recur(tycon).subst(tparams, args) + new ctx.SubstApproxMap(tparams, args).apply(recur(tycon)) } record(tp, baseTp) baseTp diff --git a/tests/pos/i5844.scala b/tests/pos/i5844.scala new file mode 100644 index 000000000000..ca735de7eaf0 --- /dev/null +++ b/tests/pos/i5844.scala @@ -0,0 +1,26 @@ +package p1 { + trait A + trait B[X, Y]{ + def m(): X + } + trait C[X] extends B[X, X & A] + + object O{ + def m(c: C[_]) = { + val x = c.m() + } + } +} +package p2 { + trait A + trait B[X]{ + def m(): X + } + trait C[X] extends B[X with A] + + object O{ + def m(c: C[_]) = { + val x: A = c.m() + } + } +} \ No newline at end of file