summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-10-14 07:02:00 -0700
committerGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-10-14 07:02:00 -0700
commitd068b163d36b3fbffe39f87e3dc152a14c3ca07e (patch)
treef1cf3a2cb12c7e9a353430f4684588e3d5892243
parent92f06b1f129b4eafb799f0d0b33e52156c06bc9b (diff)
parent4f1a46c98afeeb57bd79d339c2be3280cdb41273 (diff)
downloadscala-d068b163d36b3fbffe39f87e3dc152a14c3ca07e.tar.gz
scala-d068b163d36b3fbffe39f87e3dc152a14c3ca07e.tar.bz2
scala-d068b163d36b3fbffe39f87e3dc152a14c3ca07e.zip
Merge pull request #3038 from retronym/topic/by-name-revert
SI-7899 Allow by-name inference under -Yinfer-by-name
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala6
-rw-r--r--test/files/run/t7899-regression.check1
-rw-r--r--test/files/run/t7899-regression.flags1
-rw-r--r--test/files/run/t7899-regression.scala24
5 files changed, 35 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 1f80aa4b6f..01d5791f60 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -176,8 +176,8 @@ trait ScalaSettings extends AbsScalaSettings
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Yreploutdir = StringSetting ("-Yrepl-outdir", "path", "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" , "")
val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
- val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").
- withDeprecationMessage("This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug.")
+ val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").withDeprecationMessage(removalIn212)
+ val inferByName = BooleanSetting ("-Yinfer-by-name", "Allow inference of by-name types. This is a temporary option to ease transition. See SI-7899.").withDeprecationMessage(removalIn212)
val Yinvalidate = StringSetting ("-Yinvalidate", "classpath-entry", "Invalidate classpath entry before run", "")
val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes")
val YdisableUnreachablePrevention = BooleanSetting("-Ydisable-unreachable-prevention", "Disable the prevention of unreachable blocks in code generation.")
@@ -185,6 +185,8 @@ trait ScalaSettings extends AbsScalaSettings
val exposeEmptyPackage = BooleanSetting("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
+ private def removalIn212 = "This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug."
+
/** Area-specific debug output.
*/
val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index ccf4a5e46f..dd0923a696 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -913,7 +913,11 @@ trait Infer extends Checkable {
val targs = exprTypeArgs(tvars, tparams, treeTp, pt, useWeaklyCompatible)
def infer_s = map3(tparams, tvars, targs)((tparam, tvar, targ) => s"$tparam=$tvar/$targ") mkString ","
printTyping(tree, s"infer expr instance from pt=$pt, $infer_s")
- def targsStrict = if (targs eq null) null else targs mapConserve dropByName
+
+ // SI-7899 infering by-name types is unsound. The correct behaviour is conditional because the hole is
+ // exploited in Scalaz (Free.scala), as seen in: run/t7899-regression.
+ def dropByNameIfStrict(tp: Type): Type = if (settings.inferByName) tp else dropByName(tp)
+ def targsStrict = if (targs eq null) null else targs mapConserve dropByNameIfStrict
if (keepNothings || (targs eq null)) { //@M: adjustTypeArgs fails if targs==null, neg/t0226
substExpr(tree, tparams, targsStrict, pt)
diff --git a/test/files/run/t7899-regression.check b/test/files/run/t7899-regression.check
new file mode 100644
index 0000000000..602b03a1d1
--- /dev/null
+++ b/test/files/run/t7899-regression.check
@@ -0,0 +1 @@
+warning: -Yinfer-by-name is deprecated: This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug.
diff --git a/test/files/run/t7899-regression.flags b/test/files/run/t7899-regression.flags
new file mode 100644
index 0000000000..553a27eafd
--- /dev/null
+++ b/test/files/run/t7899-regression.flags
@@ -0,0 +1 @@
+-Yinfer-by-name -deprecation
diff --git a/test/files/run/t7899-regression.scala b/test/files/run/t7899-regression.scala
new file mode 100644
index 0000000000..67d38cdd1d
--- /dev/null
+++ b/test/files/run/t7899-regression.scala
@@ -0,0 +1,24 @@
+import language.higherKinds
+
+object Test {
+ trait Monad[M[_]] {
+ def foo[A](ma: M[A])(f: M[A] => Any) = f(ma)
+ }
+ implicit def function1Covariant[T]: Monad[({type l[a] = (T => a)})#l] =
+ new Monad[({type l[a] = (T => a)})#l] {}
+
+ def main(args: Array[String]) {
+ // inference of T = (=> Any) here was outlawed by SI-7899 / 8ed7099
+ // but this pattern is used in Scalaz in just a few places and caused
+ // a regression.
+ //
+ // Inference of a by-name type doesn't *always* lead to a ClassCastException,
+ // it only gets there if a method in generic code accepts a parameter of
+ // that type.
+ //
+ // We need to introduce the stricter inference rules gradually, probably
+ // with a warning.
+ val m = implicitly[Monad[({type f[+x] = (=> Any) => x})#f]]
+ assert(m.foo[Int]((x => 0))(f => f(???)) == 0)
+ }
+}