Skip to content

Commit f806073

Browse files
committed
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 scala/scala-dev#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
1 parent 4e564ef commit f806073

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

src/reflect/scala/reflect/internal/Definitions.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -837,9 +837,9 @@ trait Definitions extends api.StandardDefinitions {
837837
* The class defining the method is a supertype of `tp` that
838838
* has a public no-arg primary constructor.
839839
*/
840-
def samOf(tp: Type): Symbol = if (!doSam) NoSymbol else {
840+
def samOf(tp: Type): Symbol = if (!doSam) NoSymbol else if (!isNonRefinementClassType(unwrapToClass(tp))) NoSymbol else {
841841
// look at erased type because we (only) care about what ends up in bytecode
842-
// (e.g., an alias type or intersection type is fine as long as the intersection dominator compiles to an interface)
842+
// (e.g., an alias type is fine as long as is compiles to a single-abstract-method)
843843
val tpSym: Symbol = erasure.javaErasure(tp).typeSymbol
844844

845845
if (tpSym.exists && tpSym.isClass
Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,62 @@
1-
sammy_restrictions.scala:35: error: type mismatch;
1+
sammy_restrictions.scala:38: error: type mismatch;
22
found : () => Int
33
required: NoAbstract
44
(() => 0) : NoAbstract
55
^
6-
sammy_restrictions.scala:36: error: type mismatch;
6+
sammy_restrictions.scala:39: error: type mismatch;
77
found : Int => Int
88
required: TwoAbstract
99
((x: Int) => 0): TwoAbstract
1010
^
11-
sammy_restrictions.scala:37: error: type mismatch;
11+
sammy_restrictions.scala:40: error: type mismatch;
1212
found : Int => Int
1313
required: NoEmptyConstructor
1414
((x: Int) => 0): NoEmptyConstructor
1515
^
16-
sammy_restrictions.scala:38: error: type mismatch;
16+
sammy_restrictions.scala:41: error: type mismatch;
1717
found : Int => Int
1818
required: MultipleConstructorLists
1919
((x: Int) => 0): MultipleConstructorLists
2020
^
21-
sammy_restrictions.scala:39: error: type mismatch;
21+
sammy_restrictions.scala:42: error: type mismatch;
2222
found : Int => Int
2323
required: OneEmptySecondaryConstructor
2424
((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call.
2525
^
26-
sammy_restrictions.scala:40: error: type mismatch;
26+
sammy_restrictions.scala:43: error: type mismatch;
2727
found : Int => Int
2828
required: MultipleMethodLists
2929
((x: Int) => 0): MultipleMethodLists
3030
^
31-
sammy_restrictions.scala:41: error: type mismatch;
31+
sammy_restrictions.scala:44: error: type mismatch;
3232
found : Int => Int
3333
required: ImplicitConstructorParam
3434
((x: Int) => 0): ImplicitConstructorParam
3535
^
36-
sammy_restrictions.scala:42: error: type mismatch;
36+
sammy_restrictions.scala:45: error: type mismatch;
3737
found : Int => Int
3838
required: ImplicitMethodParam
3939
((x: Int) => 0): ImplicitMethodParam
4040
^
41-
sammy_restrictions.scala:43: error: type mismatch;
41+
sammy_restrictions.scala:46: error: type mismatch;
4242
found : Int => Int
4343
required: PolyMethod
4444
((x: Int) => 0): PolyMethod
4545
^
46-
sammy_restrictions.scala:44: error: type mismatch;
46+
sammy_restrictions.scala:47: error: type mismatch;
4747
found : Int => Int
4848
required: SelfTp
4949
((x: Int) => 0): SelfTp
5050
^
51-
10 errors found
51+
sammy_restrictions.scala:48: error: type mismatch;
52+
found : Int => Int
53+
required: T1 with U1
54+
((x: Int) => 0): T1 with U1
55+
^
56+
sammy_restrictions.scala:49: error: type mismatch;
57+
found : Int => Int
58+
required: Test.NonClassTypeRefinement
59+
(which expands to) DerivedOneAbstract with OneAbstract
60+
((x: Int) => 0): NonClassTypeRefinement
61+
^
62+
12 errors found

test/files/neg/sammy_restrictions.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ abstract class DerivedOneAbstract extends OneAbstract
2727
abstract class SelfTp { self: NoAbstract => def ap(a: Int): Any }
2828
abstract class SelfVar { self => def ap(a: Int): Any }
2929

30+
trait T1 { def t(a: Int): Int }; trait U1
31+
3032
object Test {
3133
implicit val s: String = ""
32-
type NonClassType = DerivedOneAbstract with OneAbstract
34+
type NonClassTypeRefinement = DerivedOneAbstract with OneAbstract
35+
type NonClassType = DerivedOneAbstract
3336

3437
// errors:
3538
(() => 0) : NoAbstract
@@ -42,6 +45,8 @@ object Test {
4245
((x: Int) => 0): ImplicitMethodParam
4346
((x: Int) => 0): PolyMethod
4447
((x: Int) => 0): SelfTp
48+
((x: Int) => 0): T1 with U1
49+
((x: Int) => 0): NonClassTypeRefinement
4550

4651
// allowed:
4752
((x: Int) => 0): OneEmptyConstructor

0 commit comments

Comments
 (0)