From ee265a645c17ee8ee3d5a5dd74a1b7371338b8df Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Jan 2018 13:14:22 +0100 Subject: [PATCH 1/2] Fix #3012: Avoid swallowing multiple ()'s Allow dropping at most one () if a method is called that exists in both ()T and => T forms. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +++++- tests/neg/i3012/Fuzbar.java | 4 ++++ tests/neg/i3012/a.scala | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i3012/Fuzbar.java create mode 100644 tests/neg/i3012/a.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index a562e69acc00..8acacf1950eb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -64,6 +64,7 @@ object Typer { private val ExprOwner = new Property.Key[Symbol] private val InsertedApply = new Property.Key[Unit] + private val DroppedEmptyArgs = new Property.Key[Unit] } class Typer extends Namer with TypeAssigner with Applications with Implicits with Dynamic with Checking with Docstrings { @@ -1862,6 +1863,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit * * 0th strategy: If `tree` overrides a nullary method, mark the prototype * so that the argument is dropped and return `tree` itself. + * (but do this at most once per tree). * * After that, two strategies are tried, and the first that is successful is picked. * If neither of the strategies are successful, continues with`fallBack`. @@ -1899,7 +1901,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit pt match { case pt @ FunProto(Nil, _, _) - if tree.symbol.allOverriddenSymbols.exists(_.info.isNullaryMethod) => + if tree.symbol.allOverriddenSymbols.exists(_.info.isNullaryMethod) && + tree.getAttachment(DroppedEmptyArgs).isEmpty => + tree.putAttachment(DroppedEmptyArgs, ()) pt.markAsDropped() tree case _ => diff --git a/tests/neg/i3012/Fuzbar.java b/tests/neg/i3012/Fuzbar.java new file mode 100644 index 000000000000..2818d4f6455e --- /dev/null +++ b/tests/neg/i3012/Fuzbar.java @@ -0,0 +1,4 @@ +package fuz; +public interface Fuzbar { + public String str(); +} \ No newline at end of file diff --git a/tests/neg/i3012/a.scala b/tests/neg/i3012/a.scala new file mode 100644 index 000000000000..a02998d1c16b --- /dev/null +++ b/tests/neg/i3012/a.scala @@ -0,0 +1,5 @@ + +object a extends fuz.Fuzbar { + override def str = "" + str()()()()()() // error: missing argument +} From c299da9ba8a2fe69b3a7bb41b3aae2740685da0d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 8 Jan 2018 10:18:41 +0100 Subject: [PATCH 2/2] Address review comments --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 12 ++++++++++++ tests/neg/i3012/a.scala | 3 +++ 2 files changed, 15 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 8acacf1950eb..c9458c547aec 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -62,8 +62,20 @@ object Typer { if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable) assert(tree.pos.exists, s"position not set for $tree # ${tree.uniqueId}") + /** A context property that indicates the owner of any expressions to be typed in the context + * if that owner is different from the context's owner. Typically, a context with a class + * as owner would have a local dummy as ExprOwner value. + */ private val ExprOwner = new Property.Key[Symbol] + + /** An attachment on a Select node with an `apply` field indicating that the `apply` + * was inserted by the Typer. + */ private val InsertedApply = new Property.Key[Unit] + + /** An attachment on a tree `t` occurring as part of a `t()` where + * the `()` was dropped by the Typer. + */ private val DroppedEmptyArgs = new Property.Key[Unit] } diff --git a/tests/neg/i3012/a.scala b/tests/neg/i3012/a.scala index a02998d1c16b..29f65430f05c 100644 --- a/tests/neg/i3012/a.scala +++ b/tests/neg/i3012/a.scala @@ -2,4 +2,7 @@ object a extends fuz.Fuzbar { override def str = "" str()()()()()() // error: missing argument + str()() // error: missing argument + str() // ok + str // ok }