Skip to content

Commit

Permalink
SI-9943 sealed class does not yield SAM type
Browse files Browse the repository at this point in the history
This is a bit of a sneaky fix for this bug, but our hand
is pretty much forced by other constraints, in this intersection
of overload resolution involving built-in function types and SAMs,
and type inference for higher-order function literals (scala#5307).

Luckily, in this particular issue, the overloading clash seems accidental.
The `<:<` class is not a SAM type as it cannot be subclassed outside
of `Predef`. For simplicity, we don't consider where the SAM conversion
occurs and exclude all sealed classes from yielding SAM types.
  • Loading branch information
adriaanm committed Oct 4, 2016
1 parent 1f6006d commit 437af11
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 1 deletion.
1 change: 1 addition & 0 deletions spec/06-expressions.md
Expand Up @@ -1361,6 +1361,7 @@ Note that a function literal that targets a SAM is not necessarily compiled to t

It follows that:
- if class `C` defines a constructor, it must be accessible and must define exactly one, empty, argument list;
- class `C` cannot be sealed (for simplicity, we don't consider the case of SAM conversion in the same compilation unit as the sealed type);
- `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`.

Expand Down
2 changes: 1 addition & 1 deletion src/reflect/scala/reflect/internal/Definitions.scala
Expand Up @@ -847,7 +847,7 @@ trait Definitions extends api.StandardDefinitions {
// (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
if (tpSym.exists && tpSym.isClass && !tpSym.isSealed
// if tp has a constructor (its class is not a trait), it must be public and must not take any arguments
// (implementation restriction: implicit argument lists are excluded to simplify type inference in adaptToSAM)
&& { val ctor = tpSym.primaryConstructor
Expand Down
9 changes: 9 additions & 0 deletions test/files/pos/t9943.scala
@@ -0,0 +1,9 @@
class Foo[T] {
def toMap[K, V](implicit ev: Foo[T] <:< Foo[(K, V)]): Foo[Map[K, V]] = null
def toMap[K](keySelector: T => K): Foo[Map[K, T]] = null
}

object Foo {
(??? : Foo[Int]) toMap (_ % 2)
(??? : Foo[(Int, String)]).toMap
}

0 comments on commit 437af11

Please sign in to comment.