From ae0e1263c22e6b94b112a2b4b00a49853f0e3d58 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 24 Oct 2015 21:51:27 +0200 Subject: [PATCH 1/4] Less eager tvar interpolation: wait until method calls are fully applied Fix #738 --- src/dotty/tools/dotc/typer/Typer.scala | 13 +++++++++++-- tests/pos/tparam_inf.scala | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/pos/tparam_inf.scala diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 6510ba35b0b7..47cd1cd1857b 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -563,7 +563,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val pos = params indexWhere (_.name == param.name) if (pos < mtpe.paramTypes.length) { val ptype = mtpe.paramTypes(pos) - if (isFullyDefined(ptype, ForceDegree.none)) return ptype + if (isFullyDefined(ptype, ForceDegree.noBottom)) return ptype } case _ => } @@ -1265,7 +1265,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = /*>|>*/ track("adapt") /*<|<*/ { /*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ { - interpolateUndetVars(tree, if (tree.isDef) tree.symbol else NoSymbol) + val isMethodCall = + tree.tpe.widen match { + case (_: MethodType) | (_: PolyType) if !tree.isDef => + true + case _ => + false + } + if (!isMethodCall) // Delay tvar interpolation in method calls until they're fully applied + interpolateUndetVars(tree, if (tree.isDef) tree.symbol else NoSymbol) + tree.overwriteType(tree.tpe.simplified) adaptInterpolated(tree, pt, original) } diff --git a/tests/pos/tparam_inf.scala b/tests/pos/tparam_inf.scala new file mode 100644 index 000000000000..7b0ee0b36688 --- /dev/null +++ b/tests/pos/tparam_inf.scala @@ -0,0 +1,12 @@ +object Test { + def foo1[T](x: T)(implicit ev: T): Nothing = ??? + def foo2[T](x: T)(implicit ev: T): T = ??? + + def test: Unit = { + implicit val ii: Int = 42 + + foo1(10) + foo2(10) + } +} + From 6d8f3730ca4d381b105737edaff6f8794b54e848 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 24 Oct 2015 22:09:59 +0200 Subject: [PATCH 2/4] Fix issue that prevented instantiating some tvars before implicit search --- src/dotty/tools/dotc/typer/Inferencing.scala | 2 +- tests/pos/tparam_inf.scala | 30 ++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index f414d3bce112..ac4ad1b35624 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -141,7 +141,7 @@ object Inferencing { if (toTest.isEmpty) acc else tree match { case Apply(fn, _) => - fn.tpe match { + fn.tpe.widen match { case mtp: MethodType => val (occ, nocc) = toTest.partition(tvar => mtp.paramTypes.exists(tvar.occursIn)) occurring(fn, nocc, occ ::: acc) diff --git a/tests/pos/tparam_inf.scala b/tests/pos/tparam_inf.scala index 7b0ee0b36688..16d99b75d538 100644 --- a/tests/pos/tparam_inf.scala +++ b/tests/pos/tparam_inf.scala @@ -1,12 +1,38 @@ +class HasFoo[T] { + val x: Foo[T] = ??? +} +class Foo[T] { + def get(x: T): T = x + def get2(x: T): Nothing = ??? + + def foo1(x: T)(implicit ev: T): Nothing = ??? + def foo2(x: T)(implicit ev: T): T = ??? + def foo3[Dummy](x: T)(implicit ev: T): Nothing = ??? + def foo4[Dummy](x: T)(implicit ev: T): T = ??? +} + object Test { + def foo1[T](x: T)(implicit ev: T): Nothing = ??? def foo2[T](x: T)(implicit ev: T): T = ??? - def test: Unit = { + def test1: Unit = { implicit val ii: Int = 42 foo1(10) foo2(10) } -} + def hf[T]: HasFoo[T] = ??? + def test2: Unit = { + implicit val ii: Int = 42 + + hf.x.get(10) + hf.x.get2(10) + + hf.x.foo1(10) + hf.x.foo2(10) + hf.x.foo3(10) + hf.x.foo4(10) + } +} From e83e8944c5757d4b60de796a505925fa2f1bb4f7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 25 Oct 2015 15:14:49 +0100 Subject: [PATCH 3/4] Simplify logic in adapt --- src/dotty/tools/dotc/typer/Typer.scala | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 47cd1cd1857b..e0a1c502c6c7 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1265,16 +1265,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = /*>|>*/ track("adapt") /*<|<*/ { /*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ { - val isMethodCall = - tree.tpe.widen match { - case (_: MethodType) | (_: PolyType) if !tree.isDef => - true - case _ => - false - } - if (!isMethodCall) // Delay tvar interpolation in method calls until they're fully applied - interpolateUndetVars(tree, if (tree.isDef) tree.symbol else NoSymbol) - + if (tree.isDef) interpolateUndetVars(tree, tree.symbol) + else if (!tree.tpe.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol) tree.overwriteType(tree.tpe.simplified) adaptInterpolated(tree, pt, original) } From 875d7da572b2367222e3021edcecb2d3cb33cefa Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sun, 25 Oct 2015 15:34:35 +0100 Subject: [PATCH 4/4] Readd `.widen` which was accidentally removed from the previous commit --- src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index e0a1c502c6c7..52ea32bbc1be 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1266,7 +1266,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = /*>|>*/ track("adapt") /*<|<*/ { /*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ { if (tree.isDef) interpolateUndetVars(tree, tree.symbol) - else if (!tree.tpe.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol) + else if (!tree.tpe.widen.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol) tree.overwriteType(tree.tpe.simplified) adaptInterpolated(tree, pt, original) }