bug
bug copied to clipboard
Confusing error message involving stabilized term
class Outer {
class Inner() {}
def getInner = new Inner()
def useInner(inner: Inner): Unit = {
}
}
class Container {
var outer: Outer = _
outer = new Outer
}
class UseContainer(c: Container) {
import c.outer
outer.useInner(outer.getInner)
}
in Scala 2.13.1 this code does not compile with the following error:
type mismatch;
[error] found : Outer#Inner
[error] required: stabilizer$1.Inner
[error] outer.useInner(outer.getInner)
[error] ^
[error] one error found
Using c.outer
directly, instead of importing it compiles ok (as well as replacing var with a val, etc).
I expected that importing a var from some instance should be equivalent to using it directly, is that wrong?
To clarify, only version 3 compiles:
$ cat t11808.scala
class Outer {
class Inner() {}
def getInner = new Inner()
def useInner(inner: Inner): Unit = {
}
}
class Container {
var outer: Outer = new Outer
}
class UseContainer3(c: Container) {
val stable = c.outer
stable.useInner(stable.getInner)
}
class UseContainer2(c: Container) {
c.outer.useInner(c.outer.getInner)
}
class UseContainer(c: Container) {
import c.outer
outer.useInner(outer.getInner)
}
The other examples compile the same:
$ scalac t11808.scala
t11808.scala:15: error: type mismatch;
found : Outer#Inner
required: stabilizer$1.Inner
c.outer.useInner(c.outer.getInner)
^
t11808.scala:19: error: type mismatch;
found : Outer#Inner
required: stabilizer$1.Inner
outer.useInner(outer.getInner)
^
two errors found
The message could be friendlier. Similarly for implicit parameter:
error: could not find implicit value for parameter x: stabilizer$1.Inner
Yep, looks like I made a mistake while checking version w/o import, and this is not related to imports at all.
Edited out my s/z
joke. It was a case of the wag dogging the title.
Here's another one. This is with Scala 2.13.
case class T0() {
type A
def f(a: A): A =
a
}
T0().f(2)
type mismatch;
found : Int(2)
required: stabilizer$1.A
T0().f(2)
The error should make it more clear what to do and what is wrong.
It seems like it should be not possible to create an instance of a class without its abstract types being something concrete.
Another example of where it goes wrong:
val t0 = T0()
classOf[t0.A]
gives
class type required but t0.A found
classOf[t0.A]
It seems like it should be not possible to create an instance of a class without its abstract types being something concrete.
That is allowed. Everyone is surprised to learn.
Scala 3 attempts to be more helpful:
15 | c.outer.useInner(c.outer.getInner)
| ^^^^^^^^^^^^^^^^
| Found: Outer#Inner
| Required: ?1.Inner
|
| where: ?1 is an unknown value of type Outer
|
| longer explanation available when compiling with `-explain`
|----------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| Tree: UseContainer.this.c.outer.getInner
| I tried to show that
| Outer#Inner
| conforms to
| ?2.Inner
| but the comparison trace ended with `false`:
|
| ==> Outer#Inner <: ?2.Inner
| ==> Outer <: (?2 : Outer)
| <== Outer <: (?2 : Outer) = false
| <== Outer#Inner <: ?2.Inner = false
|
| The tests were made under the empty constraint
----------------------------------------------------------------------------
Same with this.type
instead of members. Arguably, this is more confusing. (oh pun, this
is more confusing.)
Welcome to Scala 2.13.13 (OpenJDK 64-Bit Server VM, Java 21.0.2).
Type in expressions for evaluation. Or try :help.
scala> class C { def f(x: this.type): Unit = () }
class C
scala> new C().f("")
^
error: type mismatch;
found : String("")
required: stabilizer$1.type
scala>
Scala 3
scala> new C().f("")
-- [E007] Type Mismatch Error: -----------------------------------------------------------------------------------------
1 |new C().f("")
| ^^
| Found: ("" : String)
| Required: (?1 : C)
|
| where: ?1 is an unknown value of type C
|
| longer explanation available when compiling with `-explain`
1 error found
Well, it's a bit misleading to call it an unknown value. It knows exactly what value it's using, the expression it just evaluated.