Skip to content

Compiler error caused by import of unrelated extension #13558

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
armingensler opened this issue Sep 18, 2021 · 3 comments · Fixed by #13588
Closed

Compiler error caused by import of unrelated extension #13558

armingensler opened this issue Sep 18, 2021 · 3 comments · Fixed by #13588

Comments

@armingensler
Copy link

Compiler version

3.0.2

Minimized code

package testcode

class A

class B

object ExtensionA {
  extension (self: A) {
    def id = "A"
  }
}
object ExtensionB {
  extension (self: B) {
    def id = "B"
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    import ExtensionA._
    import ExtensionB._ // without this include the code compiles
    val a = A()
    println(a.id)
  }
}

Output

[error] -- [E008] Not Found Error: E:\Programmieren\scala3_sbt_test2\src\main\scala\testcode\Foo.scala:23:14
[error] 23 |    println(a.id)
[error]    |            ^^^^
[error]    |      value id is not a member of testcode.A.
[error]    |      An extension method was tried, but could not be fully constructed:
[error]    |
[error]    |          testcode.ExtensionB.id(a)    failed with
[error]    |
[error]    |              Found:    (a : testcode.A)
[error]    |              Required: testcode.B

Expectation

It should not ambiguous which extension to use and therefore the ExtensionB import should not matter.

@armingensler armingensler changed the title Compiler error coaused by import of unrelated extension Compiler error caused by import of unrelated extension Sep 18, 2021
@odersky
Copy link
Contributor

odersky commented Sep 22, 2021

It would be nice if this worked, but it does not work this way. a.id coming from the context is resolved the same as id(a). If you write id(a) instead, you get:

-- [E049] Reference Error: i13558.scala:23:12 ----------------------------------
23 |    println(id(a))
   |            ^^
   |            Reference to id is ambiguous,
   |            it is both imported by import testcode.ExtensionA._
   |            and imported subsequently by import testcode.ExtensionB._

longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: i13558.scala:23:15 ------------------------------
23 |    println(id(a))
   |               ^
   |               Found:    (a : testcode.A)
   |               Required: testcode.B

longer explanation available when compiling with `-explain`
2 errors found

Crucially, two subsequent imports do not created an overloaded reference. They are simply ambiguous. The only thing to do here is to improve the error message so that the ambiguity gets mentioned.

@soronpo
Copy link
Contributor

soronpo commented Sep 22, 2021

The problem is that this limitation piles on yet-another-thing-that-implicit-classes-can-do-and-extension-methods-can't.
https://scastie.scala-lang.org/64hBEjr3RdiE0xS50FDtEQ

class A

class B

object ExtensionA {
  implicit class ICA(self: A) {
    def id = "A"
  }
}
object ExtensionB {
  implicit class ICB(self: B) {
    def id = "B"
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    import ExtensionA._
    import ExtensionB._
    val a = A()
    println(a.id)
  }
}

@soronpo
Copy link
Contributor

soronpo commented Sep 22, 2021

The workaround for this limitation is to use export:
https://scastie.scala-lang.org/Q0ZU4yYsTXeUPra3RQ7qZQ

class A

class B

object ExtensionA {
  extension (self: A) {
    def id = "A"
  }
}
object ExtensionB {
  extension (self: B) {
    def id = "B"
  }
}
object ExtensionAB{
  export ExtensionA._
  export ExtensionB._
}

object Main {
  def main(args: Array[String]): Unit = {
    import ExtensionAB._
    val a = A()
    println(a.id)
    val b = B()
    println(b.id)
  }
}

@Kordyjan Kordyjan added this to the 3.1.1 milestone Aug 2, 2023
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.

5 participants