Permalink
Browse files

SI-5683 Fail gracefully when transposing a ragged type arg matrix.

The code used to do this, until `transpose` starting throwing IAE
rather than AIOOBE.

Symptomatic treatment only: The reported crasher now infers ill-kinded
type args and reports an error.
  • Loading branch information...
retronym committed May 26, 2012
1 parent 85cd96d commit 80d986997e58b5195654b6f9ca8cd81bc62f4bbf
@@ -6572,47 +6572,50 @@ trait Types extends api.Types { self: SymbolTable =>
else Some(typeRef(pre, sym, List(lub(args))))
}
}
- else {
- val args = map2(sym.typeParams, argss.transpose) { (tparam, as) =>
- if (depth == 0) {
- if (tparam.variance == variance) {
- // Take the intersection of the upper bounds of the type parameters
- // rather than falling all the way back to "Any", otherwise we end up not
- // conforming to bounds.
- val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass)
- if (bounds0.isEmpty) AnyClass.tpe
- else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym)))
+ else transposeSafe(argss) match {
+ case None =>
+ // transpose freaked out because of irregular argss
+ // catching just in case (shouldn't happen, but also doesn't cost us)
+ // [JZ] It happens: see SI-5683.
+ debuglog("transposed irregular matrix!?" +(tps, argss))
+ None
+ case Some(argsst) =>
+ val args = map2(sym.typeParams, argsst) { (tparam, as) =>
+ if (depth == 0) {
+ if (tparam.variance == variance) {
+ // Take the intersection of the upper bounds of the type parameters
+ // rather than falling all the way back to "Any", otherwise we end up not
+ // conforming to bounds.
+ val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass)
+ if (bounds0.isEmpty) AnyClass.tpe
+ else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym)))
+ }
+ else if (tparam.variance == -variance) NothingClass.tpe
+ else NoType
}
- else if (tparam.variance == -variance) NothingClass.tpe
- else NoType
- }
- else {
- if (tparam.variance == variance) lub(as, decr(depth))
- else if (tparam.variance == -variance) glb(as, decr(depth))
else {
- val l = lub(as, decr(depth))
- val g = glb(as, decr(depth))
- if (l <:< g) l
+ if (tparam.variance == variance) lub(as, decr(depth))
+ else if (tparam.variance == -variance) glb(as, decr(depth))
+ else {
+ val l = lub(as, decr(depth))
+ val g = glb(as, decr(depth))
+ if (l <:< g) l
else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
// just err on the conservative side, i.e. with a bound that is too high.
// if(!(tparam.info.bounds contains tparam)) //@M can't deal with f-bounds, see #2251
- val qvar = commonOwner(as) freshExistential "" setInfo TypeBounds(g, l)
- capturedParams += qvar
- qvar.tpe
+ val qvar = commonOwner(as) freshExistential "" setInfo TypeBounds(g, l)
+ capturedParams += qvar
+ qvar.tpe
+ }
}
}
}
- }
- if (args contains NoType) None
- else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)))
+ if (args contains NoType) None
+ else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)))
}
} catch {
case ex: MalformedType => None
- case ex: IndexOutOfBoundsException => // transpose freaked out because of irregular argss
- // catching just in case (shouldn't happen, but also doesn't cost us)
- debuglog("transposed irregular matrix!?"+ (tps, argss))
- None
}
case SingleType(_, sym) :: rest =>
val pres = tps map (_.prefix)
@@ -201,6 +201,12 @@ trait Collections {
}
true
}
+
+ final def transposeSafe[A](ass: List[List[A]]): Option[List[List[A]]] = try {
+ Some(ass.transpose)
+ } catch {
+ case _: IllegalArgumentException => None
+ }
}
object Collections extends Collections { }
View
@@ -0,0 +1,16 @@
+t5683.scala:12: error: inferred kinds of the type arguments (Object,Int) do not conform to the expected kinds of the type parameters (type M,type B).
+Object's type parameters do not match type M's expected parameters:
+class Object has no type parameters, but type M has one
+ val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] }
+ ^
+t5683.scala:12: error: type mismatch;
+ found : Int => Test.W[String,Int]
+ required: Int => M[B]
+ val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] }
+ ^
+t5683.scala:12: error: type mismatch;
+ found : Test.K[M,Int,B]
+ required: Test.K[Test.StringW,Int,Int]
+ val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] }
+ ^
+three errors found
View
@@ -0,0 +1,23 @@
+object Test {
+ trait NT[X]
+ trait W[W, A] extends NT[Int]
+ type StringW[T] = W[String, T]
+ trait K[M[_], A, B]
+
+ def k[M[_], B](f: Int => M[B]): K[M, Int, B] = null
+
+ val okay1: K[StringW,Int,Int] = k{ (y: Int) => null: StringW[Int] }
+ val okay2 = k[StringW,Int]{ (y: Int) => null: W[String, Int] }
+
+ val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] }
+
+ // remove `extends NT[Int]`, and the last line gives an inference error
+ // rather than a crash.
+ // test/files/pos/t5683.scala:12: error: no type parameters for method k: (f: Int => M[B])Test.K[M,Int,B] exist so that it can be applied to arguments (Int => Test.W[String,Int])
+ // --- because ---
+ // argument expression's type is not compatible with formal parameter type;
+ // found : Int => Test.W[String,Int]
+ // required: Int => ?M[?B]
+ // val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] }
+ // ^
+}

0 comments on commit 80d9869

Please sign in to comment.