summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2016-07-28 15:08:43 -0700
committerLukas Rytz <lukas.rytz@gmail.com>2016-08-10 13:51:56 +0200
commit43ba65fa11456899b3c45be14bd3895d8d6b6b5a (patch)
treeaf6f3122e7f8dbb12431840c5a440e763269f478 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parent2b172be8c83c3146d3fd5ab01546c171ab18fa46 (diff)
downloadscala-43ba65fa11456899b3c45be14bd3895d8d6b6b5a.tar.gz
scala-43ba65fa11456899b3c45be14bd3895d8d6b6b5a.tar.bz2
scala-43ba65fa11456899b3c45be14bd3895d8d6b6b5a.zip
SI-7187 deprecate eta-expansion of zero-arg method values
For backwards compatiblity with 2.11, we already don't adapt a zero-arg method value to a SAM. In 2.13, we won't do any eta-expansion for zero-arg method values, but we should deprecate first.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala47
1 files changed, 30 insertions, 17 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ba104fb7a6..91cff54bc7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -872,16 +872,32 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case Block(_, tree1) => tree1.symbol
case _ => tree.symbol
}
- def shouldEtaExpandToSam: Boolean = {
- // SI-9536 don't adapt parameterless method types to a to SAM's, fall through to empty application
- // instead for backwards compatiblity with 2.11. See comments of that ticket and SI-7187
- // for analogous trouble with non-SAM eta expansion. Suggestions there are: a) deprecate eta expansion to Function0,
- // or b) switch the order of eta-expansion and empty application in this adaptation.
- !mt.params.isEmpty && samOf(pt).exists
- }
- if (!meth.isConstructor && (isFunctionType(pt) || shouldEtaExpandToSam)) { // (4.2)
+
+ def cantAdapt =
+ if (context.implicitsEnabled) MissingArgsForMethodTpeError(tree, meth)
+ else setError(tree)
+
+ // constructors do not eta-expand
+ if (meth.isConstructor) cantAdapt
+ // (4.2) eta-expand method value when function or sam type is expected
+ else if (isFunctionType(pt) || (!mt.params.isEmpty && samOf(pt).exists)) {
+ // SI-9536 `!mt.params.isEmpty &&`: for backwards compatiblity with 2.11,
+ // we don't adapt a zero-arg method value to a SAM
+ // In 2.13, we won't do any eta-expansion for zero-arg method values, but we should deprecate first
+
debuglog(s"eta-expanding $tree: ${tree.tpe} to $pt")
checkParamsConvertible(tree, tree.tpe)
+
+ // SI-7187 eta-expansion of zero-arg method value is deprecated, switch order of (4.3) and (4.2) in 2.13
+ def isExplicitEtaExpansion = original match {
+ case Typed(_, Function(Nil, EmptyTree)) => true // tree shape for `f _`
+ case _ => false
+ }
+ if (mt.params.isEmpty && !isExplicitEtaExpansion) {
+ currentRun.reporting.deprecationWarning(tree.pos, NoSymbol,
+ s"Eta-expansion of zero-argument method values is deprecated. Did you intend to write ${Apply(tree, Nil)}?", "2.12.0")
+ }
+
val tree0 = etaExpand(context.unit, tree, this)
// #2624: need to infer type arguments for eta expansion of a polymorphic method
@@ -895,12 +911,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
else
typed(tree0, mode, pt)
}
- else if (!meth.isConstructor && mt.params.isEmpty) // (4.3)
- adapt(typed(Apply(tree, Nil) setPos tree.pos), mode, pt, original)
- else if (context.implicitsEnabled)
- MissingArgsForMethodTpeError(tree, meth)
- else
- setError(tree)
+ // (4.3) apply to empty argument list -- TODO 2.13: move this one case up to avoid eta-expanding at arity 0
+ else if (mt.params.isEmpty) adapt(typed(Apply(tree, Nil) setPos tree.pos), mode, pt, original)
+ else cantAdapt
}
def adaptType(): Tree = {
@@ -4398,11 +4411,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
* (2) If $e$ is a parameterless method or call-by-name parameter of type `=>$T$`, `$e$ _` represents
* the function of type `() => $T$`, which evaluates $e$ when it is applied to the empty parameterlist `()`.
*/
- def typedEta(methodValue: Tree): Tree = methodValue.tpe match {
+ def typedEta(methodValue: Tree, original: Tree): Tree = methodValue.tpe match {
case tp@(MethodType(_, _) | PolyType(_, MethodType(_, _))) => // (1)
val formals = tp.params
if (isFunctionType(pt) || samMatchesFunctionBasedOnArity(samOf(pt), formals)) methodValue
- else adapt(methodValue, mode, checkArity(methodValue)(functionTypeWildcard(formals.length)))
+ else adapt(methodValue, mode, checkArity(methodValue)(functionTypeWildcard(formals.length)), original)
case TypeRef(_, ByNameParamClass, _) | NullaryMethodType(_) => // (2)
val pos = methodValue.pos
@@ -5106,7 +5119,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case Typed(expr, Function(Nil, EmptyTree)) =>
typed1(suppressMacroExpansion(expr), mode, pt) match {
case macroDef if treeInfo.isMacroApplication(macroDef) => MacroEtaError(macroDef)
- case methodValue => typedEta(checkDead(methodValue))
+ case methodValue => typedEta(checkDead(methodValue), tree)
}
case Typed(expr, tpt) =>
val tpt1 = typedType(tpt, mode) // type the ascribed type first