From 3a8f70881c4e2298008cadee4def9d13cebcbe12 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Aug 2015 13:09:07 -0700 Subject: Add test case --- tests/run/liftedTry.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/run/liftedTry.scala b/tests/run/liftedTry.scala index 5ff4add6d..ff9af98ec 100644 --- a/tests/run/liftedTry.scala +++ b/tests/run/liftedTry.scala @@ -12,7 +12,7 @@ object Test { foo(try 3 catch handle) - def main(args: Array[String]): Unit = { + def main(args: Array[String]) = { assert(x == 1) assert(foo(2) == 2) assert(foo(try raise(3) catch handle) == 3) @@ -20,7 +20,6 @@ object Test { } } - object Tr { def fun(a: Int => Unit) = a(2) def foo: Int = { -- cgit v1.2.3 From 5e48d1c25e9fe1f5c6b962a6edb209e587150b86 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 9 Aug 2015 15:22:42 -0700 Subject: Add test case --- tests/pos/i739.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/pos/i739.scala (limited to 'tests') diff --git a/tests/pos/i739.scala b/tests/pos/i739.scala new file mode 100644 index 000000000..340478f4f --- /dev/null +++ b/tests/pos/i739.scala @@ -0,0 +1,10 @@ +class Foo + +object Test { + def foo[T](x: T)(implicit ev: T): T = ??? + + def test: Unit = { + implicit val evidence: Foo = new Foo + foo(new Foo) + } +} -- cgit v1.2.3 From 7f983665985d93c735d519f7d24d9ba072b26cd4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 9 Aug 2015 15:29:20 -0700 Subject: Added neg test (scalac and dotty both produce an error here) --- tests/neg/i739.scala | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/neg/i739.scala (limited to 'tests') diff --git a/tests/neg/i739.scala b/tests/neg/i739.scala new file mode 100644 index 000000000..5385fa42c --- /dev/null +++ b/tests/neg/i739.scala @@ -0,0 +1,7 @@ +class Foo[A, B] +class Test { + implicit val f: Foo[Int, String] = ??? + def t[A, B >: A](a: A)(implicit f: Foo[A, B]) = ??? + t(1) // error +} + -- cgit v1.2.3 From 22a2c79adf3acb8b5dd341b552e499bced58c537 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 18 Sep 2015 17:51:45 +0200 Subject: Generalize set of typevars instantiated before implicit search We now also consider type variables in a selection prefix of the application. The test case was augmented to include a snippet which only succeeds under the generalization. --- src/dotty/tools/dotc/typer/Inferencing.scala | 57 +++++++++++++++++----------- tests/pos/i739.scala | 7 ++++ 2 files changed, 42 insertions(+), 22 deletions(-) (limited to 'tests') diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index a5cf8c4eb..0a76f45c5 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -17,6 +17,7 @@ import Decorators._ import Uniques._ import ErrorReporting.{errorType, DiagnosticString} import config.Printers._ +import annotation.tailrec import collection.mutable trait Inferencing { this: Checking => @@ -115,32 +116,44 @@ trait Inferencing { this: Checking => res } } - - /** If `tree`'s type is of the form - * - * e [T1, ..., Tn] (ps1)...(psn) - * - * the list of uninstantiated type variables matching one of `T1`, ..., `Tn` - * which also appear in one of the parameter sections `ps1`, ..., `psn`, otherwise Nil. + + /** The list of uninstantiated type variables bound by some prefix of type `T` which + * occur in at least one formal parameter type of a prefix application. + * Considered prefixes are: + * - The function `f` of an application node `f(e1, .., en)` + * - The function `f` of a type application node `f[T1, ..., Tn]` + * - The prefix `p` of a selection `p.f`. + * - The result expression `e` of a block `{s1; .. sn; e}`. */ def tvarsInParams(tree: Tree)(implicit ctx: Context): List[TypeVar] = { - def occursInParam(mtp: Type, tvar: TypeVar, secCount: Int): Boolean = mtp match { - case mtp: MethodType => - secCount > 0 && ( - mtp.paramTypes.exists(tvar.occursIn) || - occursInParam(mtp.resultType, tvar, secCount - 1)) - case _ => false - } - def collect(tree: Tree, secCount: Int): List[TypeVar] = tree match { - case Apply(fn, _) => collect(fn, secCount + 1) - case TypeApply(_, targs) => - targs.tpes.collect { - case tvar: TypeVar - if !tvar.isInstantiated && occursInParam(tree.tpe, tvar, secCount) => tvar + @tailrec def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = tree match { + case Apply(fn, _) => boundVars(fn, acc) + case TypeApply(fn, targs) => + val tvars = targs.tpes.collect { + case tvar: TypeVar if !tvar.isInstantiated => tvar } - case _ => Nil + boundVars(fn, acc ::: tvars) + case Select(pre, _) => boundVars(pre, acc) + case Block(_, expr) => boundVars(expr, acc) + case _ => acc } - collect(tree, 0) + @tailrec def occurring(tree: Tree, toTest: List[TypeVar], acc: List[TypeVar]): List[TypeVar] = + if (toTest.isEmpty) acc + else tree match { + case Apply(fn, _) => + fn.tpe match { + case mtp: MethodType => + val (occ, nocc) = toTest.partition(tvar => mtp.paramTypes.exists(tvar.occursIn)) + occurring(fn, nocc, occ ::: acc) + case _ => + occurring(fn, toTest, acc) + } + case TypeApply(fn, targs) => occurring(fn, toTest, acc) + case Select(pre, _) => occurring(pre, toTest, acc) + case Block(_, expr) => occurring(expr, toTest, acc) + case _ => acc + } + occurring(tree, boundVars(tree, Nil), Nil) } /** The instantiation direction for given poly param computed diff --git a/tests/pos/i739.scala b/tests/pos/i739.scala index 340478f4f..61fed4e5d 100644 --- a/tests/pos/i739.scala +++ b/tests/pos/i739.scala @@ -3,8 +3,15 @@ class Foo object Test { def foo[T](x: T)(implicit ev: T): T = ??? + class Fn[T] { + def invoke(implicit ev: T): T = ??? + } + + def bar[T](x: T): Fn[T] = ??? + def test: Unit = { implicit val evidence: Foo = new Foo foo(new Foo) + bar(new Foo).invoke } } -- cgit v1.2.3