Skip to content

Ambigious implicit raised too soon #17769

@Adam-Vandervorst

Description

@Adam-Vandervorst

Compiler version

3.1.3-RC1-bin-20220218-29f9d33-NIGHTLY

Minimized code

trait Inclusion[L, R]:
  def forth: L => R
  def back: PartialFunction[R, L]

given Inclusion[Unit, Boolean] with
  def forth: Unit => Boolean = {case () => true}
  def back: PartialFunction[Boolean, Unit] = {case true => ()}

given Inclusion[Boolean, Int] with
  def forth: Boolean => Int = {case false => 0; case true => 1}
  def back: PartialFunction[Int, Boolean] = {case 0 => false; case 1 => true}

given [A]: Inclusion[A, (A, A)] with
  def forth: A => (A, A) = a => (a, a)
  def back: PartialFunction[(A, A), A] = {case (a1, a2) if a1 == a2 => a1}

given trans[L, M, R](using lm: Inclusion[L, M], mr: Inclusion[M, R]): Inclusion[L, R] with
  def forth: L => R = lm.forth andThen mr.forth
  def back: PartialFunction[R, L] = mr.back andThen lm.back

@main def example =
  println(summon[Inclusion[Unit, Int]].forth(()))

Output

  println(summon[Inclusion[Unit, Int]].forth(()))
                                      ^
ambiguous implicit arguments of type inclusion.this.Inclusion[<root>.this.scala.Unit, <root>.this.scala.Int] found for parameter x of method summon in object Predef$.
I found:

    inclusion$package$.this.given_Inclusion_L_R[<root>.this.scala.Unit^(inf), M(inf)
      , 
    <root>.this.scala.Int^(inf)](
      /* ambiguous: both given instance given_Inclusion_A_A_A in package inclusion and object given_Inclusion_Unit_Boolean in package inclusion match type inclusion.this.Inclusion[<root>.this.scala.Unit^, M] */
        summon[inclusion.this.Inclusion[<root>.this.scala.Unit^, M]]
    , inclusion$package$.this.given_Inclusion_Boolean_Int)

But both given instance given_Inclusion_A_A_A in package inclusion and object given_Inclusion_Unit_Boolean in package inclusion match type inclusion.this.Inclusion[<root>.this.scala.Unit^, M].

Expectation

Not fail as early (on the first ambigious parameter, without considering the type of the other).
I.e. do unification in implicit search.
E.g. infer

  println(trans[Unit, Boolean, (Int, Int)](
    using summon[Inclusion[Unit, Boolean]],
    trans[Boolean, Int, (Int, Int)]
  ).forth(()))

and run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    stat:needs triageEvery issue needs to have an "area" and "itype" label

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions