SAMType

dotty.tools.dotc.core.Types.SAMType
object SAMType

An extractor for single abstract method types. A type is a SAM type if it is a reference to a class or trait, which

  • has a single abstract method with a method type (ExprType and PolyType not allowed!) according to possibleSamMethods.
  • can be instantiated without arguments or with just () as argument.

Additionally, a SAM type may contain type aliases refinements if they refine an existing type member.

The pattern SAMType(samMethod, samParent) matches a SAM type, where samMethod is the type of the single abstract method and samParent is a subtype of the matched SAM type which has been stripped of wildcards to turn it into a valid parent type.

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
SAMType.type

Members list

Value members

Concrete methods

def samClass(tp: Type)(using Context): Symbol
def samParent(origTp: Type, samClass: Symbol, samMeth: Symbol)(using Context): Type

If possible, return a type which is both a subtype of origTp and a (possibly refined) type application of samClass where none of the type arguments are wildcards (thus making it a valid parent type), otherwise return NoType.

If possible, return a type which is both a subtype of origTp and a (possibly refined) type application of samClass where none of the type arguments are wildcards (thus making it a valid parent type), otherwise return NoType.

A wildcard in the original type will be replaced by its upper or lower bound in a way that maximizes the number of possible implementations of samMeth. For example, java.util.function defines an interface equivalent to:

trait Function[T, R]:
  def apply(t: T): R

and it usually appears with wildcards to compensate for the lack of definition-site variance in Java:

(x => x.toInt): Function[? >: String, ? <: Int]

When typechecking this lambda, we need to approximate the wildcards to find a valid parent type for our lambda to extend. We can see that in apply, T only appears contravariantly and R only appears covariantly, so by minimizing the first parameter and maximizing the second, we maximize the number of valid implementations of apply which lets us implement the lambda with a closure equivalent to:

new Function[String, Int] { def apply(x: String): Int = x.toInt }

If a type parameter appears invariantly or does not appear at all in samMeth, then we arbitrarily pick the upper-bound.

Attributes

def unapply(tp: Type)(using Context): Option[(MethodType, Type)]