scala/scala3

Implicit resolution does not take type path into account

Open

#13,591 创建于 2021年9月23日

在 GitHub 查看
 (3 评论) (0 反应) (0 负责人)Scala (1,159 fork)batch import
area:implicitshelp wanteditype:enhancement

仓库指标

Star
 (6,247 star)
PR 合并指标
 (平均合并 18天 14小时) (30 天内合并 133 个 PR)

描述

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.

贡献者指南