summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2016-03-23 10:52:57 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2016-03-26 22:55:10 -0700
commit608ac2c2b9e3f6f46489e20830d8949ee7d506cf (patch)
tree8d995139a8a66f56fed90bf65f7ece5bf26d55d7 /spec
parent878e20a5243383300d3b4990146d260409bf5dfd (diff)
downloadscala-608ac2c2b9e3f6f46489e20830d8949ee7d506cf.tar.gz
scala-608ac2c2b9e3f6f46489e20830d8949ee7d506cf.tar.bz2
scala-608ac2c2b9e3f6f46489e20830d8949ee7d506cf.zip
Soften sam restrictions
Some of the earlier proposals were too strongly linked to the requirements of the Java 8 platform, which was problematic for scala.js & friends. Instead of ruling out SAM types that we can't compile to use LambdaMetaFactory, expand those during compilation to anonymous subclasses, instead of invokedynamic + LMF. Also, self types rear their ugly heads again. Align `hasSelfType` with the implementation suggested in `thisSym`'s docs.
Diffstat (limited to 'spec')
-rw-r--r--spec/06-expressions.md28
1 files changed, 18 insertions, 10 deletions
diff --git a/spec/06-expressions.md b/spec/06-expressions.md
index 2b93842a25..bf1a6acf9a 100644
--- a/spec/06-expressions.md
+++ b/spec/06-expressions.md
@@ -1358,18 +1358,26 @@ then the selection is rewritten according to the rules for
###### SAM conversion
An expression `(p1, ..., pN) => body` of function type `(T1, ..., TN) => T` is sam-convertible to the expected type `S` if the following holds:
- - `S` declares an abstract method `m` with signature `(p1: A1, ..., pN: AN): R`;
- - besides `m`, `S` must not declare other deferred value members;
- - the method `m` must have a single argument list (thus, implicit argument lists are not allowed);
- - there must be a type `U` that is a subtype of `S`, so that the expression `new U { final def m(p1: A1, ..., pN: AN): R = body }` is well-typed (`S` need not be fully defined -- the expression will have type `U`).
+ - the class `C` of `S` declares an abstract method `m` with signature `(p1: A1, ..., pN: AN): R`;
+ - besides `m`, `C` must not declare or inherit any other deferred value members;
+ - the method `m` must have a single argument list;
+ - there must be a type `U` that is a subtype of `S`, so that the expression
+ `new U { final def m(p1: A1, ..., pN: AN): R = body }` is well-typed (conforming to the expected type `S`);
+ - for the purpose of scoping, `m` should be considered a static member (`U`'s members are not in scope in `body`);
+ - `(A1, ..., AN) => R` is a subtype of `(T1, ..., TN) => T` (satisfying this condition drives type inference of unknown type parameters in `S`);
-It follows that:
- - the type `S` must have an accessible, no-argument, constructor;
- - the class of `S` must not be nested or local (it must not capture its environment, as that precludes a zero-argument constructor).
+Note that a function literal that targets a SAM is not necessarily compiled to the above instance creation expression. This is platform-dependent.
-Additionally (the following are implementation restrictions):
- - `S`'s [erases](03-types.html#type-erasure) to a trait (this allows for a more efficient encoding when the JVM is the underlying platform);
- - the class of `S` must not be `@specialized`.
+It follows that:
+ - if class `C` defines a constructor, it must be accessible and must define exactly one, empty, argument list;
+ - `m` cannot be polymorphic;
+ - it must be possible to derive a fully-defined type `U` from `S` by inferring any unknown type parameters of `C`.
+
+Finally, we impose some implementation restrictions (these may be lifted in future releases):
+ - `C` must not be nested or local (it must not capture its environment, as that results in a zero-argument constructor)
+ - `C`'s constructor must not have an implicit argument list (this simplifies type inference);
+ - `C` must not declare a self type (this simplifies type inference);
+ - `C` must not be `@specialized`.
### Method Conversions