summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-07-14 11:50:22 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-07-14 12:04:21 +1000
commitf806073d32a476d156f1b3ec24c17f35ed65b4c3 (patch)
tree2a1389a194bdcc7153eae8c0bb0dd1951721b3e4 /src/reflect
parent4e564efb04e508ccc0f479cf1a25331501927d88 (diff)
downloadscala-f806073d32a476d156f1b3ec24c17f35ed65b4c3.tar.gz
scala-f806073d32a476d156f1b3ec24c17f35ed65b4c3.tar.bz2
scala-f806073d32a476d156f1b3ec24c17f35ed65b4c3.zip
SD-183 Make refinement classes ineligible as SAMs
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
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala4
1 files changed, 2 insertions, 2 deletions
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index fe6d88e7c7..0342daf113 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -837,9 +837,9 @@ trait Definitions extends api.StandardDefinitions {
* The class defining the method is a supertype of `tp` that
* has a public no-arg primary constructor.
*/
- def samOf(tp: Type): Symbol = if (!doSam) NoSymbol else {
+ def samOf(tp: Type): Symbol = if (!doSam) NoSymbol else if (!isNonRefinementClassType(unwrapToClass(tp))) NoSymbol else {
// look at erased type because we (only) care about what ends up in bytecode
- // (e.g., an alias type or intersection type is fine as long as the intersection dominator compiles to an interface)
+ // (e.g., an alias type is fine as long as is compiles to a single-abstract-method)
val tpSym: Symbol = erasure.javaErasure(tp).typeSymbol
if (tpSym.exists && tpSym.isClass