From 3299f3b7e7fc4a2657c7eabe946ac25357f2a9e5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 17 Dec 2018 14:40:31 +0100 Subject: [PATCH 1/3] Fix #5328: Disallow repeated type application --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 ++ tests/neg/i5328.scala | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 tests/neg/i5328.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 9c7d5c36942d..ef8c8f06839a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -881,6 +881,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic => typedExpr(tree.fun, PolyProto(typedArgs, pt)) match { case ExtMethodApply(app) => app + case typedFn: TypeApply => + errorTree(tree, "illegal repeated type application") case typedFn => typedFn.tpe.widen match { case pt: PolyType => diff --git a/tests/neg/i5328.scala b/tests/neg/i5328.scala new file mode 100644 index 000000000000..14e2cab5115d --- /dev/null +++ b/tests/neg/i5328.scala @@ -0,0 +1,8 @@ +class C[X, Y] { def apply[Z](x: X, y: Y, z: Z) = (x, y, z) } + +object Test { + def f[X, Y]: C[X, Y] = new C[X, Y] + f[Int, Boolean][String](1, true, "") // OK + f[X = Int](1, true, "") // OK, Y and Z are inferred + f[X = Int][String](1, true, "") // error: illegal repeated type application +} \ No newline at end of file From d10a7b122d726ec3f32d3309c45aa589f734fbb8 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 17 Dec 2018 15:15:35 +0100 Subject: [PATCH 2/3] Update compiler/src/dotty/tools/dotc/typer/Applications.scala Co-Authored-By: odersky --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index ef8c8f06839a..541a03407376 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -881,7 +881,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => typedExpr(tree.fun, PolyProto(typedArgs, pt)) match { case ExtMethodApply(app) => app - case typedFn: TypeApply => + case _: TypeApply => errorTree(tree, "illegal repeated type application") case typedFn => typedFn.tpe.widen match { From 35687574da5d2d6c83e4b587b3387e1f59a03e24 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 17 Dec 2018 17:18:03 +0100 Subject: [PATCH 3/3] Fix check not to run after typer After typer we can get two consecutive type argument sections. If the first section consists of named parameters that leave out some parameter bindings they are supplied in the second section. I considered merging the two type parameter sections, but that would complicate too many other things. The current scheme is still unambiguous if we consider types. I.e. two consecutive argument sections match a single formal parameter section if the first section is named and the length of both argument sections together matches the number of formal parameters. Also, fix tests. --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- tests/neg/namedTypeParams.scala | 8 +++++++- tests/pos/i5328.scala | 8 ++++++++ tests/pos/namedTypeParams.scala | 4 ---- 4 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 tests/pos/i5328.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 541a03407376..6e72c0e72e3e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -881,7 +881,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => typedExpr(tree.fun, PolyProto(typedArgs, pt)) match { case ExtMethodApply(app) => app - case _: TypeApply => + case _: TypeApply if !ctx.isAfterTyper => errorTree(tree, "illegal repeated type application") case typedFn => typedFn.tpe.widen match { diff --git a/tests/neg/namedTypeParams.scala b/tests/neg/namedTypeParams.scala index 80cfae87f077..6284926dc9d8 100644 --- a/tests/neg/namedTypeParams.scala +++ b/tests/neg/namedTypeParams.scala @@ -12,5 +12,11 @@ object Test { def f[X, Y](x: X, y: Y): Int = ??? f[X = Int, String](1, "") // error // error - f[X = Int][X = Int][Y = String](1, "") // error + f[X = Int][X = Int][Y = String](1, "") // error: illegal repeated type application + + f[X = Int][Y = String](1, "") // error: illegal repeated type application + f[X = Int][String](1, "") // error: illegal repeated type application + + f[Y = String][X = Int](1, "") // error: illegal repeated type application + f[Y = String][Int](1, "") // error: illegal repeated type application } diff --git a/tests/pos/i5328.scala b/tests/pos/i5328.scala new file mode 100644 index 000000000000..9f3fabb2b5f0 --- /dev/null +++ b/tests/pos/i5328.scala @@ -0,0 +1,8 @@ +class C[X, Y] { def apply[Z](x: X, y: Y, z: Z) = (x, y, z) } + +object Test { + def f[X, Y, Z]: C[X, Y] = new C[X, Y] + f[Int, Boolean, Any][String](1, true, "") // OK + f[X = Int](1, true, "") // OK, Y and Z are inferred + f[Z = Any, X = Int](1, true, "") // OK +} \ No newline at end of file diff --git a/tests/pos/namedTypeParams.scala b/tests/pos/namedTypeParams.scala index 2938b6dbd29b..d4088296bb8a 100644 --- a/tests/pos/namedTypeParams.scala +++ b/tests/pos/namedTypeParams.scala @@ -7,9 +7,5 @@ object Test { f[X = Int](1, "") f[Y = String](1, "") - f[X = Int][Y = String](1, "") - f[X = Int][String](1, "") - f[Y = String][X = Int](1, "") - f[Y = String][Int](1, "") }