scala/scala3

Implicit resolution does not take type path into account

Open

#13,591 opened on Sep 23, 2021

View on GitHub
 (3 comments) (0 reactions) (0 assignees)Scala (6,247 stars) (1,159 forks)batch import
area:implicitshelp wanteditype:enhancement

Description

Compiler version

3.0.2

Minimized code

It's often useful to architect modules with some shared parts, as in:

trait Shared:
  class E

object ImplA extends Shared { /* ... */ }
object ImplB extends Shared { /* ... */ }

But we are kind of stuck when we want to provide type class instances that work on all shared parts. I think this approach ought to work, but currently does not:

trait Shared:
  class E

given ImplA: Shared with { /* ... */ }
given ImplB: Shared with { /* ... */ }

// The type class of interest:
class Bar[A]
object Bar:
  given (using s: Shared): Bar[s.E] = ???

Output

summon[Bar[ImplA.E]]
ambiguous implicit arguments of type Playground.Bar[Playground.ImplA.E] found for parameter x of method summon in object Predef.
I found:

    Playground.Bar.given_Bar_E(
      /* ambiguous: both object ImplA in object Playground and object ImplB in object Playground match type Playground.Shared */
        summon[Playground.Shared]
    )

But both object ImplA in object Playground and object ImplB in object Playground match type Playground.Shared.
summon[Bar[ImplA.E]](using Bar.given_Bar_E)
ambiguous implicit arguments: both object ImplA in object Playground and object ImplB in object Playground match type Playground.Shared of parameter s of given instance given_Bar_E in object Bar
summon[Bar[ImplA.E]](using Bar.given_Bar_E(using ImplA))

Ok.

Expectation

Implicit resolution should work out that the choice of ImplA or ImplB is not actually ambiguous.

Contributor guide