Skip to content

Fix owner comparison when sorting eligible implicits #10977

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1250,7 +1250,7 @@ trait Implicits:
val arity2 = sym2.info.firstParamTypes.length
if arity1 < arity2 then return true
if arity1 > arity2 then return false
compareOwner(sym1, sym2) == 1
compareOwner(sym1.owner, sym2.owner) == 1

/** Sort list of implicit references according to `prefer`.
* This is just an optimization that aims at reducing the average
Expand Down
48 changes: 48 additions & 0 deletions tests/pos/i10964.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
trait Applicative[F[_]]

trait FooT[F[_], A]
trait BarT[F[_], A]
trait QuxT[F[_], A]
trait BazT[F[_], A]
trait ZepT[F[_], A]
trait JazT[F[_], A]
trait LafT[F[_], A]
trait PogT[F[_], A]

trait Sync[F[_]]
object Sync {
implicit def syncForFooT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> FooT[F, X]] = ???
implicit def syncForBarT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> BarT[F, X]] = ???
implicit def syncForQuxT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> QuxT[F, X]] = ???
implicit def syncForBazT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> BazT[F, X]] = ???
implicit def syncForZepT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> ZepT[F, X]] = ???
implicit def syncForJazT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> JazT[F, X]] = ???
// defining additional implicits beyond the 6 above seems to result in hang/OOM
implicit def syncForLafT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> LafT[F, X]] = ???
implicit def syncForPogT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> PogT[F, X]] = ???
}

trait Ref[F[_], A]
object Ref {
trait Make[F[_]]
object Make extends MakeInstances

trait MakeInstances extends MakeLowPriorityInstances {
implicit def applicativeInstance[F[_]](implicit F: Applicative[F]): Make[F] = ???
}

trait MakeLowPriorityInstances {
implicit def syncInstance[F[_]](implicit F: Sync[F]): Make[F] = ???
}

def of[F[_], A](a: A)(implicit mk: Make[F]): F[Ref[F, A]] = ???
}

class Resource[F[_], A] {
implicit def syncForResource[F[_]](implicit F0: Sync[F]): Sync[[X] =>> Resource[F, X]] = ???

def foo(x: F[Unit])(implicit F: Applicative[F]) = {
Ref.of /*[F, (F[Unit], F[Unit])]*/ ((x, x))
()
}
}
68 changes: 68 additions & 0 deletions tests/pos/i10964a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
trait Monoid[A]
trait Semigroup[A]
trait Applicative[F[_]]

trait OptionT[F[_], A]
trait EitherT[F[_], A, B]
trait IorT[F[_], A, B]
trait WriterT[F[_], L, V]
trait Kleisli[F[_], A, B]

final class ApplicativeIdOps[A](private val a: A) extends AnyVal {
def pure[F[_]](implicit F: Applicative[F]): F[A] = ???
}

object ApplicativeSyntax {
implicit final def syntaxApplicativeId[A](a: A): ApplicativeIdOps[A] = new ApplicativeIdOps[A](a)
}

trait Sync[F[_]]

object Sync {
implicit def syncForOptionT[F[_]](implicit F0: Sync[F]): Sync[[X] =>> OptionT[F, X]] = ???
implicit def syncForEitherT[F[_], E](implicit F0: Sync[F]): Sync[[X] =>> EitherT[F, E, X]] = ???
implicit def syncForIorT[F[_], L](implicit F0: Sync[F], L0: Semigroup[L]): Sync[[X] =>> IorT[F, L, X]] = ???
implicit def syncForWriterT[F[_], L](implicit F0: Sync[F], L0: Monoid[L]): Sync[[X] =>> WriterT[F, L, X]] = ???
implicit def syncForKleisli[F[_], R](implicit F0: Sync[F]): Sync[[X] =>> Kleisli[F, R, X]] = ???
}

trait Async[F[_]] extends Sync[F]

object Async {
implicit def asyncForOptionT[F[_]](implicit F0: Async[F]): Async[[X] =>> OptionT[F, X]] = ???
implicit def asyncForEitherT[F[_], E](implicit F0: Async[F]): Async[[X] =>> EitherT[F, E, X]] = ???
implicit def asyncForIorT[F[_], L](implicit F0: Async[F], L0: Semigroup[L]): Async[[X] =>> IorT[F, L, X]] = ???
implicit def asyncForWriterT[F[_], L](implicit F0: Async[F], L0: Monoid[L]): Async[[X] =>> WriterT[F, L, X]] = ???
implicit def asyncForKleisli[F[_], R](implicit F0: Async[F]): Async[[X] =>> Kleisli[F, R, X]] = ???
}

trait Concurrent[F[_], E] extends Applicative[F]

trait Ref[F[_], A]

object Ref {
trait Make[F[_]]
object Make extends MakeInstances

trait MakeInstances extends MakeLowPriorityInstances {
implicit def concurrentInstance[F[_]](implicit F: Concurrent[F, _]): Make[F] = ???
}

trait MakeLowPriorityInstances {
implicit def syncInstance[F[_]](implicit F: Sync[F]): Make[F] = ???
}

def of[F[_], A](a: A)(implicit mk: Make[F]): F[Ref[F, A]] = ???
}


class Resource[F[_], A] {
import ApplicativeSyntax._

implicit def asyncForResource[F[_]](implicit F0: Async[F]): Async[[X] =>> Resource[F, X]] = ???

def parZip(implicit F: Concurrent[F, Throwable]) = {
Ref.of /*[F, (F[Unit], F[Unit])]*/ (().pure[F] -> ().pure[F])
()
}
}