bug icon indicating copy to clipboard operation
bug copied to clipboard

Confusing error message involving stabilized term

Open ignatich opened this issue 5 years ago • 8 comments

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?

ignatich avatar Nov 22 '19 14:11 ignatich

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

som-snytt avatar Nov 22 '19 19:11 som-snytt

Yep, looks like I made a mistake while checking version w/o import, and this is not related to imports at all.

ignatich avatar Nov 22 '19 20:11 ignatich

Edited out my s/z joke. It was a case of the wag dogging the title.

som-snytt avatar Nov 25 '19 19:11 som-snytt

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.

shawjef3 avatar Dec 06 '22 14:12 shawjef3

Another example of where it goes wrong:

val t0 = T0()
classOf[t0.A]

gives

class type required but t0.A found
  classOf[t0.A]

shawjef3 avatar Dec 06 '22 14:12 shawjef3

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.

som-snytt avatar Dec 06 '22 14:12 som-snytt

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
    ----------------------------------------------------------------------------

SethTisue avatar Aug 10 '23 23:08 SethTisue

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.

som-snytt avatar Apr 19 '24 22:04 som-snytt