Skip to content

Ambiguous Extension Method when Exported #18768

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

Closed
benhutchison opened this issue Oct 26, 2023 · 2 comments · Fixed by #18787
Closed

Ambiguous Extension Method when Exported #18768

benhutchison opened this issue Oct 26, 2023 · 2 comments · Fixed by #18787

Comments

@benhutchison
Copy link
Contributor

Compiler version

3.3.1

Minimized code

object Module:
  trait EntityDef:
    type Id
    type Record
    type Entity = (Id, Record)

    extension (e: Entity)
      def updated: Entity = e

  case class Exportee()
  object Exportee extends EntityDef:
    opaque type Id = Long
    type Record = Exportee

    def apply(id: Long): Entity = (id, Exportee())


object Client:
  export Module.*
  val x = Exportee(1L).updated


object ClientWorkingWithManualExport:
  export Module.{Exportee as _, *}
  type Exportee = Module.Exportee
  val Exportee = Module.Exportee 

  val x = Exportee(1L).updated

Scastie https://scastie.scala-lang.org/QaKMJYEPQnumCasK5Ew7Cg

Output

Found:    Playground.Client.Exportee.Entity
Required: ?{ updated: ? }
Note that implicit extension methods cannot be applied because they are ambiguous;
both method Exportee in object Client and object Exportee in object Module provide an extension method `updated` on Playground.Client.Exportee.Entity

Expectation

There should be no ambiguity resolving the extension method updated. There is only one method and only one path to the method.

We can see in ClientWorkingWithManualExport that when we "manually" create aliases to export Exportee, rather than via an export statement, it compiles OK. In contrast, in Client the same call fails to compile.

@benhutchison benhutchison added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 26, 2023
@nicolasstucki
Copy link
Contributor

Minimization

object Module:
  object Exportee:

    opaque type Id = Long

    def apply(): Id = ???

    extension (e: Id)
      def updated: Id = ???


object Client:
  export Module.*
  val x = Exportee().updated

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Oct 27, 2023

In the minimized version we see that the extension method is not in the companion object of Id. To fix this

- extension (e: Id)
-   def updated: Id = ???
+ object Id:
+   extension (e: Id)
+     def updated: Id = ???

But this does not seem to help with the original code.

@nicolasstucki nicolasstucki added area:extension-methods area:export and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 27, 2023
odersky added a commit to dotty-staging/dotty that referenced this issue Oct 29, 2023
In implicit or extension method search we might get two alternatives that are different
but that point to the same singleton type after widening ExprTypes. In that case we can
arbitrarily pick one of them instead of declaring an ambiguity.

Fixes scala#18768
odersky added a commit that referenced this issue Oct 30, 2023
…pes (#18787)

In implicit or extension method search we might get two alternatives
that are different but that point to the same singleton type after
widening ExprTypes. In that case we can arbitrarily pick one of them
instead of declaring an ambiguity.

Fixes #18768
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants