| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Only non-refinement class types need apply, which is the same
restriction that we levy on parent types of a class.
```
scala> class C; class D extends C; type CD = C with D; class E extends CD
<console>:11: error: class type required but C with D found
class C; class D extends C; type CD = C with D; class E extends CD
^
scala> class C; class D extends C; type DC = D with C; class E extends DC
<console>:11: error: class type required but D with C found
class C; class D extends C; type DC = D with C; class E extends DC
^
```
Prior to this change:
```
scala> trait T { def t(a: Any): Any }; trait U; abstract class C extends T
defined trait T
defined trait U
defined class C
````
For indy-based lambdas:
```
scala> val tu: T with U = x => x
tu: T with U = $$Lambda$1812/317644782@3c3c4a71
scala> tu: U
java.lang.ClassCastException: $$Lambda$1812/317644782 cannot be cast to U
... 30 elided
```
For anon class based lambdas:
```
scala> ((x => x): C with U)
<console>:14: error: class type required but C with U found
((x => x): C with U)
^
scala> implicit def anyToCWithU(a: Any): C with U = new C with U { def t(a: Any) = a }
warning: there was one feature warning; re-run with -feature for details
anyToCWithU: (a: Any)C with U
scala> (((x: Any) => x): C with U) // SAM chosen but fails to typecheck the expansion uncurry
<console>:17: error: class type required but C with U found
(((x: Any) => x): C with U) // SAM chosen but fails to typecheck the expansion uncurry
^
```
Fixes https://github.com/scala/scala-dev/issues/183
While it is tempting to special case refinement classes with no decls by
flattening their parents into the parents of the lambda. But there are
some subtle issues at play with lineriazation order, as Martin pointed out
when I brought this up before: http://www.scala-lang.org/old/node/6817.html
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
Also test roundtripping serialization of a lambda that targets a
SAM that's not FunctionN (it should make no difference).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
They both compile to INDY/MetaLambdaFactory, except when they
occur in a constructor call. (TODO: can we lift the ctor arg
expression to a method and avoid statically synthesizing
anonymous subclass altogether?)
Typers:
- no longer synthesize SAMs -- *adapt* a Function literal
to the expected (SAM/FunctionN) type
- Deal with polymorphic/existential sams (relevant tests:
pos/t8310, pos/t5099.scala, pos/t4869.scala) We know where
to find the result type, as all Function nodes have a
FunctionN-shaped type during erasure. (Including function
literals targeting a SAM type -- the sam type is tracked as
the *expected* type.)
Lift restriction on sam types being class types. It's enough
that they dealias to one, like regular instance creation
expressions.
Contexts:
- No longer need encl method hack for return in sam.
Erasure:
- erasure preserves SAM type for function nodes
- Normalize sam to erased function type during erasure,
otherwise we may box the function body from `$anonfun(args)`
to `{$anonfun(args); ()}` because the expected type for the
body is now `Object`, and thus `Unit` does not conform.
Delambdafy:
- must set static flag before calling createBoxingBridgeMethod
- Refactored `createBoxingBridgeMethod` to wrap my head around
boxing, reworked it to generalize from FunctionN's boxing
needs to arbitrary LMF targets.
Other refactorings: ThisReferringMethodsTraverser, TreeGen.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Don't naively derive types for the single method's signature
from the provided function's type, as it may be a subtype
of the method's MethodType.
Instead, once the sam class type is fully defined, determine
the sam's info as seen from the class's type, and use those
to generate the correct override.
```
scala> Arrays.stream(Array(1, 2, 3)).map(n => 2 * n + 1).average.ifPresent(println)
5.0
scala> IntStream.range(1, 4).forEach(println)
1
2
3
```
Also, minimal error reporting
Can't figure out how to do it properly, but some reporting
is better than crashing. Right? Test case that illustrates
necessity of the clumsy stop gap `if (block exists (_.isErroneous))`
enclosed as `sammy_error_exist_no_crash`
added TODO for repeated and by-name params
|
|
Only one seems to indicate something new:
((x: Int) => 0): NonClassType
I believe that we shouldn't pursue SAM translation for that case,
and fallthrough to Function1. That would allow for an implicit view
to finish the job.
|