scala/scala3

Implicit resolution does not take type path into account

Open

#13.591 aperta il 23 set 2021

Vedi su GitHub
 (3 commenti) (0 reazioni) (0 assegnatari)Scala (1159 fork)batch import
area:implicitshelp wanteditype:enhancement

Metriche repository

Star
 (6247 star)
Metriche merge PR
 (Merge medio 18g 14h) (133 PR mergiate in 30 g)

Descrizione

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.

Guida contributor