summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Definitions.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2016-01-19 18:47:10 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2016-03-26 09:31:57 -0700
commit236d0e0db8b4c53837bd580e2b2022d86afde456 (patch)
tree897e8694338eb40cc1e54c3b0f0a1ccafd331866 /src/reflect/scala/reflect/internal/Definitions.scala
parent4f4fb45d7bc41564c3ba0483c5a663172e063994 (diff)
downloadscala-236d0e0db8b4c53837bd580e2b2022d86afde456.tar.gz
scala-236d0e0db8b4c53837bd580e2b2022d86afde456.tar.bz2
scala-236d0e0db8b4c53837bd580e2b2022d86afde456.zip
Refactor typedFunction, rework synthesizeSAMFunction for sammy
`typedFunction` uniformly recognizes Single Abstract Method types and built-in `FunctionN` types, type checking literals regardless of expected type. `adapt` synthesizes an anonymous subclass of the SAM type, if needed to meet the expected (non-`FunctionN`) type. (Later, we may want to carry `Function` AST nodes with SAM types through the whole pipeline until the back-end, and treat them uniformly with built-in function types there too, emitting the corresponding `invokedynamic` & `LambdaMetaFactory` bytecode. Would be faster to avoid synthesizing all this code during type checking...) Refactor `typedFunction` for performance and clarity to avoid non-local returns. A nice perk is that the error message for missing argument types now indicates with `<error>` where they are missing (see updated check file). Allow pattern matching function literals when SAM type is expected (SI-8429). Support `return` in function body of SAM target type, by making the synthetic `sam$body` method transparent to the `enclMethod` chain, so that the `return` is interpreted in its original context. A cleaner approach to inferring unknown type params of the SAM method. Now that `synthesizeSAMFunction` operates on typed `Function` nodes, we can take the types of the parameters and the body and compare them against the function type that corresponds to the SAM method's signature. Since we are reusing the typed body, we do need to change owners for the symbols, and substitute the new method argument symbols for the function's vparam syms. Impl Notes: - The shift from typing as a regular Function for SAM types was triggered by limitation of the old approach, which deferred type checking the body until it was in the synthetic SAM type subclass, which would break if the expression was subsequently retypechecked for implicit search. Other problems related to SAM expansion in ctor args also are dodged now. - Using `<:<`, not `=:=`, in comparing `pt`, as `=:=` causes `NoInstance` exceptions when `WildcardType`s are encountered. - Can't use method type subtyping: method arguments are in invariant pos. - Can't use STATIC yet, results in illegal bytecode. It would be a better encoding, since the function body should not see members of SAM class. - This is all battle tested by running `synthesizeSAMFunction` on all `Function` nodes while bootstrapping, including those where a regular function type is expected. The only thing that didn't work was regarding Function0 and the CBN transform, which breaks outer path creation in lambdalift.
Diffstat (limited to 'src/reflect/scala/reflect/internal/Definitions.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index a031f4f797..425502d25f 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -675,6 +675,17 @@ trait Definitions extends api.StandardDefinitions {
// Note that these call .dealiasWiden and not .normalize, the latter of which
// tends to change the course of events by forcing types.
def isFunctionType(tp: Type) = isFunctionTypeDirect(tp.dealiasWiden)
+ // the number of arguments expected by the function described by `tp` (a FunctionN or SAM type),
+ // or `-1` if `tp` does not represent a function type or SAM
+ def functionArityFromType(tp: Type) = {
+ val dealiased = tp.dealiasWiden
+ if (isFunctionTypeDirect(dealiased)) dealiased.typeArgs.length - 1
+ else samOf(tp) match {
+ case samSym if samSym.exists => samSym.info.params.length
+ case _ => -1
+ }
+ }
+
def isTupleType(tp: Type) = isTupleTypeDirect(tp.dealiasWiden)
def tupleComponents(tp: Type) = tp.dealiasWiden.typeArgs