summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-08-19 10:23:11 +0200
committerJason Zaugg <jzaugg@gmail.com>2013-08-19 10:36:44 +0200
commit6634d82f74b71dd36ca1ecceea08b4ad79335da0 (patch)
tree91c1603918f24bd3075e2bda155cc6d4c85e6431 /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
parent5084b74048f7f21f38fdf45ebfa8e634b863bb01 (diff)
downloadscala-6634d82f74b71dd36ca1ecceea08b4ad79335da0.tar.gz
scala-6634d82f74b71dd36ca1ecceea08b4ad79335da0.tar.bz2
scala-6634d82f74b71dd36ca1ecceea08b4ad79335da0.zip
SI-1980 A lint warning for by-name parameters in right assoc methods
The desugaring of right associative calls happens in the parser. This eagerly evaluates the arguments (to preserve left-to-right evaluation order the arguments are evaluated before the qualifier). This is pretty surprising if the method being called has a by-name parameter in the first parameter section. This commit adds a warning under -Xlint when defining such a method. The relevent spec snippets: > SLS 4.6.1 says that call-by-name argument "is not evaluated at the point of function application, but instead is evaluated at each use within the function". > > But 6.12.3 offers: > "If op is right- associative, the same operation is interpreted as { val x=e1; e2.op(x ) }, where x is a fresh name."
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala14
1 files changed, 14 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 1b6963b598..333d867797 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1371,6 +1371,16 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
member.typeParams.map(_.info.bounds.hi.widen) foreach checkAccessibilityOfType
}
+ private def checkByNameRightAssociativeDef(tree: DefDef) {
+ tree match {
+ case DefDef(_, name, _, params :: _, _, _) =>
+ if (settings.lint && !treeInfo.isLeftAssoc(name.decodedName) && params.exists(p => isByName(p.symbol)))
+ unit.warning(tree.pos,
+ "by-name parameters will be evaluated eagerly when called as a right-associative infix operator. For more details, see SI-1980.")
+ case _ =>
+ }
+ }
+
/** Check that a deprecated val or def does not override a
* concrete, non-deprecated method. If it does, then
* deprecation is meaningless.
@@ -1594,6 +1604,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
if (!sym.isConstructor && !sym.isEffectivelyFinal && !sym.isSynthetic)
checkAccessibilityOfReferencedTypes(tree)
}
+ tree match {
+ case dd: DefDef => checkByNameRightAssociativeDef(dd)
+ case _ =>
+ }
tree
case Template(parents, self, body) =>