From 335351bfa44d744fe0d55c850a38b932b52edf4b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 18 Mar 2019 09:37:24 +0100 Subject: [PATCH 1/2] Hardening in the presence of kind mismatches Three fixes for when the number of type-parameters disagrees with the number of type arguments. One is in TypeAccumulator, two more are in Substituters. There's a tricky balance here. On the one hand, crashing early on mismatches is an excellent means to pinpoint errors in the compiler. On the other hand, it makes legal but nonsensical programs crash the compiler. So, we should do the minimum so that "on the other hand" is not observed. Which means doing this driven by counter-examples (coming from fuzzing or elsewhere) is not a bad way to tackle the problem. --- compiler/src/dotty/tools/dotc/core/Substituters.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Types.scala | 5 +---- tests/neg/i6064.scala | 4 ++++ 3 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 tests/neg/i6064.scala diff --git a/compiler/src/dotty/tools/dotc/core/Substituters.scala b/compiler/src/dotty/tools/dotc/core/Substituters.scala index f39ec9a33913..f90cdf72baa4 100644 --- a/compiler/src/dotty/tools/dotc/core/Substituters.scala +++ b/compiler/src/dotty/tools/dotc/core/Substituters.scala @@ -58,7 +58,7 @@ trait Substituters { this: Context => val sym = tp.symbol var fs = from var ts = to - while (fs.nonEmpty) { + while (fs.nonEmpty && ts.nonEmpty) { if (fs.head eq sym) return ts.head fs = fs.tail ts = ts.tail @@ -203,7 +203,7 @@ trait Substituters { this: Context => val sym = tp.symbol var fs = from var ts = to - while (fs.nonEmpty) { + while (fs.nonEmpty && ts.nonEmpty) { if (fs.head eq sym) return ts.head match { case TypeBounds(lo, hi) => range(lo, hi) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 57164795b402..f5a2b55f9e8d 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4791,10 +4791,7 @@ object Types { case tp @ AppliedType(tycon, args) => @tailrec def foldArgs(x: T, tparams: List[ParamInfo], args: List[Type]): T = - if (args.isEmpty) { - assert(tparams.isEmpty) - x - } + if (args.isEmpty || tparams.isEmpty) x else { val tparam = tparams.head val acc = args.head match { diff --git a/tests/neg/i6064.scala b/tests/neg/i6064.scala new file mode 100644 index 000000000000..6ca85cdc731f --- /dev/null +++ b/tests/neg/i6064.scala @@ -0,0 +1,4 @@ +trait Trait[X] { + def f[C[_]](arg: C[X]): Int + val a = f[(Int, String)] // error +} \ No newline at end of file From 09ae674c2fe4ec74d3e86a30edef94dd6f4fb389 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 18 Mar 2019 09:42:41 +0100 Subject: [PATCH 2/2] Additional test case --- tests/neg/i6063.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/neg/i6063.scala diff --git a/tests/neg/i6063.scala b/tests/neg/i6063.scala new file mode 100644 index 000000000000..6da7badc0073 --- /dev/null +++ b/tests/neg/i6063.scala @@ -0,0 +1,12 @@ +object i0 { +trait I1[i0, I1] +def I1[I1[I1]](I1: I1[ ; // error +I1[I1] +} + +object test { +object I0 { +trait i2[I1, i2] +def i2[i2[i2]](i2: i2[ ]) = i2 // error +i2[i2]} +} \ No newline at end of file