Skip to content
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

Structural types which specify concrete versions of generic methods can lead to runtime failures #2672

Open
scabug opened this issue Nov 19, 2009 · 11 comments
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) help wanted structural types
Milestone

Comments

@scabug
Copy link

scabug commented Nov 19, 2009

This is extracted from the later comments of ticket #2144, which was otherwise addressed.

object Test {
  class MyGraph[V <: Any] {
    def addVertex(v: V): Boolean = true
  }

  type DuckGraph = {
    def addVertex(vertex: Int): Boolean
  }
  
  def fail(graph: DuckGraph) = graph addVertex 1

  def main(args: Array[String]): Unit = {
    fail(new MyGraph[Int])
  }
}
$$ scala Test
java.lang.NoSuchMethodException: Test$$MyGraph.addVertex(int)
@scabug
Copy link
Author

scabug commented Nov 19, 2009

Imported From: https://issues.scala-lang.org/browse/SI-2672?orig=1
Reporter: @paulp
See #2144

@scabug
Copy link
Author

scabug commented Jun 14, 2010

@dubochet said:
Upping crashers to hight priority.

@scabug
Copy link
Author

scabug commented Jul 3, 2010

@dubochet said:
Also confirm that the fix for this bug fixes the following:

class C[+T](val x: { var y : T })
object A extends C[Int](new { var y = 1 })
(A:C[Any]).x.y = ""
java.lang.NoSuchMethodException: A$$$$anon$$1.y_$$eq(java.lang.Object)

@scabug
Copy link
Author

scabug commented Jan 17, 2011

Erik Bruchez (ebruchez) said:
Definitely would like to see this one fixed as it kills an ideal use case for structural types. For reference my scenario posted to scala-user:

http://goo.gl/9Y7mw

Related StackOverflow question:

http://stackoverflow.com/questions/4702664/

@scabug
Copy link
Author

scabug commented Mar 8, 2011

@paulp said:
Assigning to meeting because I have an implementation to see.

@scabug
Copy link
Author

scabug commented Oct 19, 2012

@lrytz said:
Another NoSuchMethodException, maybe the same bug, maybe not:

val o = new {
  def f(x: Object) = new {
    def g(y: x.type) = 0
  }
}
val s = ""
o.f(s).g(s)

@scabug
Copy link
Author

scabug commented Oct 19, 2012

@paulp said:
I'd think we should just disallow that signature. It's not like it's going to know a method which takes an x.type if it sees one.

Actually that's a bug, and then there's also a bug that it's generating a call to a (String)Unit method. Where def g is declared x is an Object - I wonder how it's even getting its hands on "String"...

@scabug
Copy link
Author

scabug commented Oct 19, 2012

@lrytz said:
I can't follow what you are saying.

What should be disallowed? I think the code makes perfect sense, and the type checker is able to handle it correctly. Only it crashes at run-time.

scala> val o = new {
     |   def f(x: Object) = new {
     |     def g(y: x.type) = 0
     |   }
     | }
o: Object{def f(x: Object): Object{def g(y: x.type): Int}} = $anon$1@7471c619

scala> val s = ""
s: String = ""

scala> val o1 = o.f(s)
warning: there were 1 feature warnings; re-run with -feature for details
o1: Object{def g(y: s.type): Int} = $anon$1$$anon$2@2a11890d

scala> o1.g("huh")
<console>:11: error: type mismatch;
 found   : String("huh")
 required: s.type
              o1.g("huh")
                   ^

scala> o1.g(s)
warning: there were 1 feature warnings; re-run with -feature for details
java.lang.NoSuchMethodException: $anon$1$$anon$2.g(java.lang.String)
	at java.lang.Class.getMethod(Class.java:1605)
	at .reflMethod$Method1(<console>:11)
        [...]

@scabug
Copy link
Author

scabug commented Oct 19, 2012

@paulp said:
I was thinking analogously to the restriction on abstract types, but rather than attempt to elaborate, let me just admit that I can't follow what I was saying either. I should wait for the first coffee. Strike it all from the record.

@dwijnand
Copy link
Member

Still broken in Scala 3.0.0:

scala> object Test {
     |   class MyGraph[V <: Any] {
     |     def addVertex(v: V): Boolean = true
     |   }
     |
     |   type DuckGraph = {
     |     def addVertex(vertex: Int): Boolean
     |   }
     |
     |   def fail(graph: DuckGraph) = graph addVertex 1
     |
     |   def main(args: Array[String]): Unit = {
     |     fail(new MyGraph[Int])
     |   }
     | }
     |
10 |  def fail(graph: DuckGraph) = graph addVertex 1
   |                               ^^^^^
   |                        Found:    (graph : Test.DuckGraph)
   |                        Required: Selectable
   |
   |                        The following import might fix the problem:
   |
   |                          import reflect.Selectable.reflectiveSelectable
   |

scala> object Test {
     |   import reflect.Selectable.reflectiveSelectable
     |
     |   class MyGraph[V <: Any] {
     |     def addVertex(v: V): Boolean = true
     |   }
     |
     |   type DuckGraph = {
     |     def addVertex(vertex: Int): Boolean
     |   }
     |
     |   def fail(graph: DuckGraph) = graph addVertex 1
     |
     |   def main(args: Array[String]): Unit = {
     |     fail(new MyGraph[Int])
     |   }
     | }
// defined object Test

scala> Test.main(Array())
java.lang.NoSuchMethodException: rs$line$1$Test$MyGraph.addVertex(int)
  at java.lang.Class.getMethod(Class.java:1786)
  at scala.reflect.Selectable.applyDynamic(Selectable.scala:38)
  at scala.reflect.Selectable.applyDynamic$(Selectable.scala:11)
  at scala.reflect.Selectable$DefaultSelectable.applyDynamic(Selectable.scala:51)
  at rs$line$1$Test$.fail(rs$line$1:12)
  at rs$line$1$Test$.main(rs$line$1:15)
  ... 28 elided

Good that it requires an import, but I don't consider import reflect.Selectable.reflectiveSelectable to give that "oh this code might be unsound" feeling.

@smarter
Copy link
Member

smarter commented May 14, 2021

But not broken anymore in Scala 3 nightlies :)

15 |    fail(new MyGraph[Int])
   |         ^^^^^^^^^^^^^^^^
   |         Found:    Test.MyGraph[Int]
   |         Required: Test.DuckGraph

cf #10414 (comment)

@smarter smarter added the fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) label May 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) help wanted structural types
Projects
None yet
Development

No branches or pull requests

3 participants