question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Overconstrained GADT bounds in presence of bad bounds

See original GitHub issue

Compiler version

3.0.0-RC1 (Scastie)

Minimized code

@main def test: Unit = {
  trait S[A]
  trait Inv[A]

  class P[X] extends S[Inv[X] & Inv[String]]

  def patmat[A, Y](s: S[Inv[A] & Y]): A = s match {
    case p: P[x] =>
      "Hello"
  }
  
  val got: Int = patmat[Int, Inv[String]](new P) // ClassCastException: String cannot be cast to Integer
}

Output

Click to expand
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:99)
	at main$package$.test(main.scala:11)
	at test.main(main.scala:1)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sbt.Run.invokeMain(Run.scala:115)
	at sbt.Run.execute$1(Run.scala:79)
	at sbt.Run.$anonfun$runWithLoader$4(Run.scala:92)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
	at sbt.util.InterfaceUtil$$anon$1.get(InterfaceUtil.scala:10)
	at sbt.TrapExit$App.run(TrapExit.scala:257)
	at java.lang.Thread.run(Thread.java:748)

Expectation

The code should be rejected, but it is unclear what part is problematic:

  1. The instantiation of new P due to introducing the bad bounds S[Inv[Int] & Inv[String]]
  2. The class declaration of P with the extends S[Inv[X] & Inv[String]] clause, which may lead to bad bounds if X != String
  3. Deducing that x = A = String

I think that the problem comes from 1 (and not necessarily from 3). I believe, however, that this is not sufficient, as it seems that bad bounds can still be crafted.

Translating the above into pDOT shows that we can allow 3. if we require a witness value for Inv[A] & Y. Then, the above would not cause a ClassCastException since providing a value for Inv[Int] & Inv[String] is not possible.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:19 (19 by maintainers)

github_iconTop GitHub Comments

2reactions
abgruszeckicommented, Mar 12, 2021

I’m reopening this. @LPTK correctly observed that we’re still unsound. The correct solution seems to be to check whether we’re in GADT constraint inference mode before (approximately) branching on &.

1reaction
LPTKcommented, Feb 27, 2021

The culprit is clearly 3. In Scala/pDOT, you can’t escape type members with members that themselves end up having bad bounds (as you say, bad bounds can still be crafted). So we have to live with bad bounds.

In the pattern match, we know Inv[x] & Inv[String] =:= Inv[A] & Y. It is utterly wrong to decompose that constraint into Inv[x] =:= Inv[A] and Inv[String] =:= Y, which is what Dotty seems to be doing. The latter implies the former, so it’s okay for approximating type inference, but the former does not imply the latter.

In DOT-like terms, we have Inv[x | String .. x & String] =:= Inv[A] & Y. So we do have Inv[x | String .. x & String] <: Inv[A] and thus A <: x | String and x & String <: A. We also have Inv[A] & Y <: Inv[x | String .. x & String], from which we can’t deduce anything (think that Y could be bottom). None of these implies String <: A, which is needed to make the pattern match type check.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Generalization Bounds in the Presence of Outliers: a Median ...
Roughly, we want K > 2nO to ensure that blocks without outliers are in majority. However, if K is too large MoM tends...
Read more >
Constrained Nonlinear Optimization Algorithms - MathWorks
In this method an active set, A ¯ k , is maintained that is an estimate of the active constraints (i.e., those that...
Read more >
Channel coding: non-asymptotic fundamental limits
Knowledge of the behavior of the fundamental limits in the non-asymptotic ... Moreover, the bound (2.45) also holds in the presence of noiseless...
Read more >
RESIDUAL AND BACKWARD ERROR BOUNDS IN MINIMUM ...
The present paper proves the- oretical results motivated by the abovementioned finite precision behavior of MGS. GMRES but assumes exact arithmetic in all...
Read more >
Upper Limits on the Epoch of Reionization 21 cm Power ...
(2022) present a validation of the Phase I analysis and power spectrum pipeline, using data simulations with realistic sky, instrument, and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found