scala3
scala3 copied to clipboard
Name binding is not as ambiguous as specified
minimized code
Given a compilation unit:
package p.q
class X {
override def toString() = "p.q.X"
}
Either of these references to X should be ambiguous:
import reflect.ClassTag
package p {
class X {
override def toString() = "p.X"
}
package q {
object Test {
def f = implicitly[ClassTag[X]] // ambiguous
}
}
object Test {
def main(args: Array[String]) = println {
p.q.Test.f
}
}
}
or
import reflect.ClassTag
package p {
class X {
override def toString() = "p.X"
}
package q {
import r.X
object Test {
def f = implicitly[ClassTag[X]] // ambiguous
}
}
package r {
class X {
override def toString() = "p.r.X"
}
}
object Test {
def main(args: Array[String]) = println {
p.q.Test.f
}
}
}
Compilation output
➜ scala git:(2.13.x) skalac test/files/neg/t10662/*.scala
test/files/neg/t10662/px_2.scala:19: error: reference to X is ambiguous;
it is both defined in package p and available as class X in package q
implicitly[T[X]] // ambiguous
^
1 error
➜ scala git:(2.13.x) skalac test/files/neg/t10662b/*.scala
test/files/neg/t10662b/px_2.scala:16: error: reference to X is ambiguous;
it is both defined in package p and imported subsequently by
import r.X
implicitly[T[X]] // ambiguous
^
1 error
It compiles on both Scala 2.13.0 and 3, but Scala 2 picks p.q.X and p.r.X respectively, and Dotty picks p.X in both cases.
expectation
p.q.X has lowest precedence: it is made available by the packaging package q but cannot shadow the high priority definition p.X, and is therefore ambiguous.
Similarly for the import r.X, as imports never shadow definitions in the current file.
p.q.X has lowest precedence: it is made available by the packaging package q but cannot shadow the high priority definition p.X, and is therefore ambiguous.
Is this the behavior of scalac or something written down in the spec somewhere ?
Spec is at https://scala-lang.org/files/archive/spec/2.13/02-identifiers-names-and-scopes.html
It's fixed in 2.13.1, but as someone noted, no one writes code like that.
The linked Scala 2 PR has the two tests that should have ambiguous references.
From the OP, it looks like Dotty behavior changed, because the second test picks p.r.X, not p.X as claimed by OP:
-- Error: test/files/neg/t10662b/px_2.scala:16:22 ----------------------------------------------------------------------
16 | implicitly[T[X]] // ambiguous
| ^
| no given instance of type p.T[p.r.X] was found for parameter e of method implicitly in object Predef
1 error found
The first test still compiles in Dotty and still picks p.X:
implicitly[p.T[p.X]](p.X.tx)
What?
In the absence of p.X, the first example prints p.q.X. The presence of p.X should make X ambiguous because p.q.X cannot shadow p.X.
Contrary to whatever that guy tried last summer, test 2 is the same result. I hope he doesn't think I'm trying to "show him up" or make him look stupid.
Oh, did you try 2.13.10?
Let me try that. Yes, 2.13 correctly reports the ambiguity.
But Scala 3 has a very simple and pleasant mechanism for ranking the bindings. Maybe it's simple enough for you to understand and maybe diagnose the issue.
OK, I'll give a shot in the new year.