Skip to content

SD-183 Make refinement classes ineligible as SAMs#5279

Merged
adriaanm merged 1 commit intoscala:2.12.xfrom
retronym:ticket/SD-183
Jul 26, 2016
Merged

SD-183 Make refinement classes ineligible as SAMs#5279
adriaanm merged 1 commit intoscala:2.12.xfrom
retronym:ticket/SD-183

Conversation

@retronym
Copy link
Member

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

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
@retronym
Copy link
Member Author

Review by @adriaanm

@retronym retronym added this to the 2.12.0-RC1 milestone Jul 14, 2016
@adriaanm
Copy link
Contributor

LGTM, thanks!

@adriaanm adriaanm merged commit 4f749ce into scala:2.12.x Jul 26, 2016
@adriaanm adriaanm added the 2.12 label Oct 29, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants