diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-06-16 14:15:30 -0400 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-06-16 17:09:33 -0400 |
commit | 83ae74ce9d3ff56c47b39e44332daa3da2981133 (patch) | |
tree | 2dfcbdad1ecb2039fe606730f348c2bdb2267d19 | |
parent | 70a93f52c3efafe604d6547b335cc361deff4f29 (diff) | |
download | scala-83ae74ce9d3ff56c47b39e44332daa3da2981133.tar.gz scala-83ae74ce9d3ff56c47b39e44332daa3da2981133.tar.bz2 scala-83ae74ce9d3ff56c47b39e44332daa3da2981133.zip |
SI-7584 Fix typer regression with by-name parameter types
It regressed in fada1ef6b#L4L614. Partially reverting just
this change restores the correct behaviour:
```
- if (sym.isStable && pre.isStable && !isByNameParamType(tree.tpe) &&
+ if (treeInfo.admitsTypeSelection(tree) &&
```
This patch embeds the check for by-name parameter types into
`TreeInfo.isStableIdentifier`. That code already checks for
`Symbol#isStable`, which exludes direct references to by-name
parameters. But the additional check is required to deal with
by-name parameters in function types, e.g `(=> Int) => Any`.
Open question: should we go further and embed this check in `isStable`?
Currently:
final def isStable = isTerm && !isMutable && !(hasFlag(BYNAMEPARAM)) && (!isMethod || hasStableFlag)
Such function types are an underspecified corner of the language,
albeit one that is pretty useful writing, for example, in the
signature of a lazy foldRight that can operate over infinite
structures:
def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B): B
The next commit subjects them to a little testing.
-rw-r--r-- | src/reflect/scala/reflect/internal/TreeInfo.scala | 9 | ||||
-rw-r--r-- | test/files/pos/t7584.scala | 11 |
2 files changed, 19 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 3a8d3fd460..a5cf46071f 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -98,7 +98,7 @@ abstract class TreeInfo { */ def isStableIdentifier(tree: Tree, allowVolatile: Boolean): Boolean = tree match { - case Ident(_) => symOk(tree.symbol) && tree.symbol.isStable && !tree.symbol.hasVolatileType // TODO SPEC: not required by spec + case i @ Ident(_) => isStableIdent(i) case Select(qual, _) => isStableMemberOf(tree.symbol, qual, allowVolatile) && isPath(qual, allowVolatile) case Apply(Select(free @ Ident(_), nme.apply), _) if free.symbol.name endsWith nme.REIFY_FREE_VALUE_SUFFIX => // see a detailed explanation of this trick in `GenSymbols.reifyFreeTerm` @@ -119,6 +119,13 @@ abstract class TreeInfo { typeOk(tree.tpe) && (allowVolatile || !hasVolatileType(tree)) && !definitions.isByNameParamType(tree.tpe) ) + private def isStableIdent(tree: Ident): Boolean = ( + symOk(tree.symbol) + && tree.symbol.isStable + && !definitions.isByNameParamType(tree.tpe) + && !tree.symbol.hasVolatileType // TODO SPEC: not required by spec + ) + /** Is `tree`'s type volatile? (Ignored if its symbol has the @uncheckedStable annotation.) */ def hasVolatileType(tree: Tree): Boolean = diff --git a/test/files/pos/t7584.scala b/test/files/pos/t7584.scala new file mode 100644 index 0000000000..52d127ecb9 --- /dev/null +++ b/test/files/pos/t7584.scala @@ -0,0 +1,11 @@ +object Test { + def fold[A, B](f: (A, => B) => B) = ??? + def f[A, B](x: A, y: B): B = ??? + def bip[A, B] = fold[A, B]((x, y) => f(x, y)) + def bop[A, B] = fold[A, B](f) + + // these work: + fold[Int, Int]((x, y) => f(x, y)) + fold[Int, Int](f) +} + |