From b7509c922f78624a9eba88c3c64054e0d217ecea Mon Sep 17 00:00:00 2001 From: Mirco Dotta Date: Fri, 22 Nov 2013 11:55:19 +0100 Subject: SI-7548 askTypeAt returns the same type whether the source was fully or targeted type-checked When asking for targeted typecheck, the located tree may have overloaded types is the source isn't yet fully typechecked (e.g., a select tree for an overloaded method). This is problematic as it can lead to unknown 'hovers', broken hyperlinking that suddenly starts working, unresolved ScalaDoc comments, and similar, in the Scala IDE. With this commit we are hardening the contract of `askTypeAt` to return the same type whether the file was fully type-checked or targeted type-checked. This is done by preventing the typechecker to stop too early if the `located` tree has an overloaded type. Furthermore, I'm assuming that if `located.tpe` is of type `OverloadedType`, by letting the compiler carry-on the typechecking, the `located.tpe` will eventually be resolved to a non-overloaded type. Said otherwise, I expect the targeted typechecking will always terminate (if my reasoning isn't sound, please say so). The test provided with this commit demonstrates the new behavior (the position used to execute the test is resolved to the `foo` method's call). In fact, before this commit, executing the test returned the following: (x: Int, y: String)Unit (x: String)Unit (x: Int)Unit Showing that the tree's type is an overloaded type. The ambiguity is fixed by this commit, and in fact the test's output is now: (x: Int)Unit --- test/files/presentation/t7548.check | 1 + test/files/presentation/t7548/Test.scala | 17 +++++++++++++++++ test/files/presentation/t7548/src/Foo.scala | 7 +++++++ 3 files changed, 25 insertions(+) create mode 100644 test/files/presentation/t7548.check create mode 100644 test/files/presentation/t7548/Test.scala create mode 100644 test/files/presentation/t7548/src/Foo.scala (limited to 'test/files') diff --git a/test/files/presentation/t7548.check b/test/files/presentation/t7548.check new file mode 100644 index 0000000000..5bfb0d27fe --- /dev/null +++ b/test/files/presentation/t7548.check @@ -0,0 +1 @@ +(x: Int)Unit diff --git a/test/files/presentation/t7548/Test.scala b/test/files/presentation/t7548/Test.scala new file mode 100644 index 0000000000..94a6048056 --- /dev/null +++ b/test/files/presentation/t7548/Test.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest + +object Test extends InteractiveTest { + override protected def loadSources() { /* don't parse or typecheck sources */ } + + import compiler._ + + override def runDefaultTests() { + val res = new Response[Tree] + val pos = compiler.rangePos(sourceFiles.head, 102,102,102) + compiler.askTypeAt(pos, res) + res.get match { + case Left(tree) => compiler.ask(() => reporter.println(tree.tpe)) + case Right(ex) => reporter.println(ex) + } + } +} diff --git a/test/files/presentation/t7548/src/Foo.scala b/test/files/presentation/t7548/src/Foo.scala new file mode 100644 index 0000000000..cc997f6e5f --- /dev/null +++ b/test/files/presentation/t7548/src/Foo.scala @@ -0,0 +1,7 @@ +object Foo { + def foo(x: Int) = {} + def foo(x: String) = {} + def foo(x: Int, y: String) = {} + + foo(2) +} \ No newline at end of file -- cgit v1.2.3 From 652b3b4b9dcbf990e7ace409e050cc4ba4e83b16 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 1 Dec 2013 09:56:36 +0100 Subject: SI-7548 Test to demonstrate residual exploratory typing bug We shouldn't observe tree types under silent mode. The enclosed test is a standalone version of `1 + BigInt(2)`, a standard example of exploratory typing in Scala. Once we determine that none of the `+` methods in `Int` accepts (possibly implicitly coerced `BigInt`), we have to backtrack and look for a view from `Int => { +(_: BigInt): ? }`. The next commit will correct the problem. --- test/files/presentation/t7548b.check | 1 + test/files/presentation/t7548b/Test.scala | 17 +++++++++++++++++ test/files/presentation/t7548b/src/Foo.scala | 12 ++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 test/files/presentation/t7548b.check create mode 100644 test/files/presentation/t7548b/Test.scala create mode 100644 test/files/presentation/t7548b/src/Foo.scala (limited to 'test/files') diff --git a/test/files/presentation/t7548b.check b/test/files/presentation/t7548b.check new file mode 100644 index 0000000000..5ba69809f1 --- /dev/null +++ b/test/files/presentation/t7548b.check @@ -0,0 +1 @@ +Foo.this.I.+: (other: Foo.I.type)Unit diff --git a/test/files/presentation/t7548b/Test.scala b/test/files/presentation/t7548b/Test.scala new file mode 100644 index 0000000000..0c022df839 --- /dev/null +++ b/test/files/presentation/t7548b/Test.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest + +object Test extends InteractiveTest { + override protected def loadSources() { /* don't parse or typecheck sources */ } + + import compiler._ + + override def runDefaultTests() { + val res = new Response[Tree] + val pos = compiler.rangePos(sourceFiles.head, 191, 191, 191) // + + compiler.askTypeAt(pos, res) + res.get match { + case Left(tree) => compiler.ask(() => reporter.println(s"$tree: ${tree.tpe}")) + case Right(ex) => reporter.println(ex) + } + } +} diff --git a/test/files/presentation/t7548b/src/Foo.scala b/test/files/presentation/t7548b/src/Foo.scala new file mode 100644 index 0000000000..5cf0a4ef4e --- /dev/null +++ b/test/files/presentation/t7548b/src/Foo.scala @@ -0,0 +1,12 @@ +import language._ + +object Foo { + object I { + def +(other: I.type) : Unit = () + } + object BI { + def +(other: BI.type): Unit = () + } + implicit def I2BI(i: I.type): BI.type = BI + I.+(BI) +} -- cgit v1.2.3 From 02308c96910a76a09c2654db304a0696c0b603af Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 1 Dec 2013 10:03:27 +0100 Subject: SI-7458 Pres. compiler must not observe trees in silent mode Otherwise we can think that `+` in `1 + BigInt(2)` refers to a method in `Int`. In general, this protects the IDE from observing results from "exploratory" typing which is discarded as the compiler backtracks to another possibility. This protection subsumes the condition that checked for overloaded types: presentation/t7458 now passes without this. --- src/compiler/scala/tools/nsc/interactive/Global.scala | 12 +++++++----- test/files/presentation/t7548b.check | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index b4e8170b19..02a37ec217 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -238,7 +238,12 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") * @param result The transformed node */ override def signalDone(context: Context, old: Tree, result: Tree) { - if (interruptsEnabled && analyzer.lockedCount == 0) { + val canObserveTree = ( + interruptsEnabled + && analyzer.lockedCount == 0 + && !context.bufferErrors // SI-7558 look away during exploratory typing in "silent mode" + ) + if (canObserveTree) { if (context.unit.exists && result.pos.isOpaqueRange && (result.pos includes context.unit.targetPos)) { @@ -247,10 +252,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") println("something's wrong: no "+context.unit+" in "+result+result.pos) located = result } - located.tpe match { - case _: OverloadedType => () - case _ => throw new TyperResult(located) - } + throw new TyperResult(located) } else { try { diff --git a/test/files/presentation/t7548b.check b/test/files/presentation/t7548b.check index 5ba69809f1..35445fedf6 100644 --- a/test/files/presentation/t7548b.check +++ b/test/files/presentation/t7548b.check @@ -1 +1 @@ -Foo.this.I.+: (other: Foo.I.type)Unit +Foo.this.I2BI(Foo.this.I).+: (other: Foo.BI.type)Unit -- cgit v1.2.3