-
Notifications
You must be signed in to change notification settings - Fork 21
Null lower bound breaks with intersection types #1280
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
Comments
Imported From: https://issues.scala-lang.org/browse/SI-1280?orig=1 |
@dragos said: scala> trait T { type U >: Null
| type V >: Null
| }
defined trait T
scala> trait T1 extends T { type V = Any with U }
<console>:5: error: error overriding type V in trait T with bounds >: Null <: Any;
type V has incompatible type Any with T1.this.U
trait T1 extends T { type V = Any with U } |
@odersky said: |
Lauri Alanko (lealanko) said: If This rule should, as far as I can see, be safe for all types, and with the current type system it already seems to be admissible for all the types I tested with... except As further proof that this is a compiler bug, consider that the problems in both my and Iulian's example can be worked around by simply parameterizing the lower bound so a literal trait X[L] { x => type T >: L; new X[L] { type T = Any with x.T } }
trait T[L] { type U >: L; type V >: L }
trait T1[L] extends T[L] { type V = Any with U } This doesn't yield any compiler errors with 2.7.2.RC1, and there are no problems instantiating So it very very much seems to me that in the compiler there is some special-cased handling for |
@odersky said: |
Geoffrey Alan Washburn (washburn) said: |
@DRMacIver said: I can't think of a reason it shouldn't work if B >: Null though. |
Lauri Alanko (lealanko) said: Anyway, if And by my reading the above rule is already contained in the spec, in 3.5.2:
I don't see any exceptions for |
@odersky said: class B
class C(x: String) extends B
class A {
type A >: Null
class D { type T >: C <: B }
val x: D with A = null
var y: x.T = new C("abc")
}
object Test extends A with Application {
class C { type T = Int; val x = 1 }
type A = C
y = 42
} (I'll add it to the test suite as null-unsoundness.scala). If you compile the test with scalac, you get: found : Null(null)
required: A.this.D with A.this.A
val x: D with A = null
^
one error found I then changed the condition which causes the error. It's in symtab/Types, method case (_, RefinedType(parents2, ref2)) =>
(parents2 forall (tp2 => tp1 <:< tp2)) &&
(ref2.toList forall tp1.specializes) &&
(tp1.typeSymbol != NullClass ||
!parents2.exists(_.typeSymbol.isAbstractType)) I removed the last condition. Then the example compiles, but at runtime you see: Exception in thread "main" java.lang.ExceptionInInitializerError
at Test.main(nulls.scala)
Caused by: java.lang.ClassCastException: java.lang.Integer cannot be cast to B
at Test$$.<init>(nulls.scala:13)
at Test$$.<clinit>(nulls.scala)
... 1 more So, here's the type hole. In summary, ``what's wrong with the Scala type system_ is that the idea of a universal value of null is fundamentally at odds with type abstraction. The cleanest fix would be to eliminate `null'. Failing that, we have to live with the restriction, or design a different scheme. But this should be a SIP; as you can see the issues are tricky and require a lot of study. |
Lauri Alanko (lealanko) said: It seems to me that 500, 501 and this case are all various To my understanding, the underlying cause is the fact that a The fix to 501 and this case take different approaches, though: I don't think It's funny, now I realize that my ticket #1273 is completely Have I understood the situation correctly? |
Lauri Alanko (lealanko) said: class C[L, A >: L, B >: L](l : L) {
val x : A with B = l
}
class D[B >: Null] extends C[Null, { type X >: String}, B](null) {
var y : x.X = "foo"
}
val v : Int = new D[{type X <: Int}].y This yields: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
at .<init>(<console>:6) Abstract type members can also be used instead of type parameters. I guess it's possible to add some more ad-hoc checks that prevent more of these kinds of problems, but they still can't guarantee that more of the same kind won't turn up. Forbidding |
Geoffrey Alan Washburn (washburn) said: |
Geoffrey Alan Washburn (washburn) said: I've created a test in r16081 for this particular ticket. |
@paulp said: |
@adriaanm said: |
Using 2.7.2.RC1. The problem is that if
A
is a type variable with a>: Null
lower bound, then even ifB >: Null
,A with B
won't be>: Null
.Super-contrived minimal example follows:
Replace
Null
above with any other type, and it works.The text was updated successfully, but these errors were encountered: