diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index ccf02262a4df..037104d5b864 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -44,7 +44,7 @@ object Decorators { } } - final val MaxFilterRecursions = 1000 + final val MaxFilterRecursions = 100 /** Implements filterConserve, zipWithConserve methods * on lists that avoid duplication of list nodes where feasible. diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 45c5ce8586bc..85c24a7dbe10 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -129,6 +129,8 @@ object TypeApplications { def apply(t: Type): Type = t match { case t @ AppliedType(tycon, args1) if tycon.typeSymbol.isClass => t.derivedAppliedType(apply(tycon), args1.mapConserve(applyArg)) + case t @ RefinedType(parent, name, TypeAlias(info)) => + t.derivedRefinedType(apply(parent), name, applyArg(info).bounds) case p: TypeParamRef if p.binder == tycon => args(p.paramNum) match { case TypeBounds(lo, hi) => diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 7e6e801c357f..f7e431325320 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -586,10 +586,14 @@ object ProtoTypes { else if (tp.symbol.isStatic || (tp.prefix `eq` NoPrefix)) tp else tp.derivedSelect(wildApprox(tp.prefix, theMap, seen)) case tp @ AppliedType(tycon, args) => + def wildToBounds(tp: Type) = tp match { + case WildcardType(tp: TypeBounds) => tp + case tp => tp + } wildApprox(tycon, theMap, seen) match { case _: WildcardType => WildcardType // this ensures we get a * type case tycon1 => tp.derivedAppliedType(tycon1, - args.mapConserve(arg => wildApprox(arg, theMap, seen))) + args.mapConserve(arg => wildToBounds(wildApprox(arg, theMap, seen)))) } case tp: RefinedType => // default case, inlined for speed tp.derivedRefinedType( diff --git a/tests/pos/hkRefAlias.scala b/tests/pos/hkRefAlias.scala new file mode 100644 index 000000000000..58ec787def1c --- /dev/null +++ b/tests/pos/hkRefAlias.scala @@ -0,0 +1,10 @@ +class Bar +class X +class Y extends X + +object Test { + type G[X] = Bar { type R = X } + + implicitly[G[_] =:= (Bar { type R })] + implicitly[G[_ >: Y <: X] =:= (Bar { type R >: Y <: X })] +} diff --git a/tests/pos/i6238.scala b/tests/pos/i6238.scala new file mode 100644 index 000000000000..9cd6d56d95ed --- /dev/null +++ b/tests/pos/i6238.scala @@ -0,0 +1,121 @@ +object K1 { + class Foo[T] + + class Bar[F[_]] + object Bar { + implicit def barF[F[_]](implicit fooF: Foo[Bar[F]]): Bar[F] = null + } + + class A[T] + object A { + implicit def fooA[F[_[_]]](implicit barB: F[B]): Foo[F[A]] = null + } + + class B[T] + object B { + implicit def fooB[F[_[_]]]: Foo[F[B]] = null + } +} + +object K1U { + class Foo[T] + + class Bar[F[_ <: Int]] + object Bar { + implicit def barF[F[_ <: Int]](implicit fooF: Foo[Bar[F]]): Bar[F] = null + } + + class A[T <: Int] + object A { + implicit def fooA[F[_[_ <: Int]]](implicit barB: F[B]): Foo[F[A]] = null + } + + class B[T <: Int] + object B { + implicit def fooB[F[_[_ <: Int]]]: Foo[F[B]] = null + } +} + +object K1L { + class Foo[T] + + class Bar[F[_ >: Int]] + object Bar { + implicit def barF[F[_ >: Int]](implicit fooF: Foo[Bar[F]]): Bar[F] = null + } + + class A[T >: Int] + object A { + implicit def fooA[F[_[_ >: Int]]](implicit barB: F[B]): Foo[F[A]] = null + } + + class B[T >: Int] + object B { + implicit def fooB[F[_[_ >: Int]]]: Foo[F[B]] = null + } +} + +object K11 { + class Foo[T] + + class Bar[F[_[_]]] + object Bar { + implicit def barF[F[_[_]]](implicit fooF: Foo[Bar[F]]): Bar[F] = null + } + + class A[T[_]] + object A { + implicit def fooA[F[_[_[_]]]](implicit barB: F[B]): Foo[F[A]] = null + } + + class B[T[_]] + object B { + implicit def fooB[F[_[_[_]]]]: Foo[F[B]] = null + } +} + +object K2 { + class Foo[T] + + class Bar[F[_, _]] + object Bar { + implicit def barF[F[_, _]](implicit fooF: Foo[Bar[F]]): Bar[F] = null + } + + class A[T, U] + object A { + implicit def fooA[F[_[_, _]]](implicit barB: F[B]): Foo[F[A]] = null + } + + class B[T, U] + object B { + implicit def fooB[F[_[_, _]]]: Foo[F[B]] = null + } +} + +object Test { + { + import K1._ + implicitly[Bar[A]] + } + + { + import K1U._ + implicitly[Bar[A]] + } + + { + import K1L._ + implicitly[Bar[A]] + } + + { + import K11._ + implicitly[Bar[A]] + } + + { + import K2._ + implicitly[Bar[A]] + } +}