summaryrefslogtreecommitdiff
path: root/test/files/run/sammy_restrictions_LMF.scala
blob: aa49e1411339e5f6f05b61fb889001a1022c859b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
trait T[@specialized A] { def apply(a: A): A }
trait TInt extends T[Int]

trait TWithVal { val x: Any = 1; def apply(x: Int): String }

trait TImpure { def apply(x: Int): String ; println(1) }

trait Println { println(1) }
trait TImpureSuper extends Println { def apply(x: Int): String  }

class C
trait A extends C
trait B extends A
trait TClassParent extends B { def apply(x: Int): String }

object Test extends App {
  final val AnonFunClass = "$anonfun$"
  final val LMFClass = "$$Lambda$" // LambdaMetaFactory names classes like this

  private def LMF(f: Any): Unit = {
    val className = f.getClass.toString
    assert(!(className contains AnonFunClass), className)
    assert((className contains LMFClass), className)
  }

  private def notLMF(f: Any): Unit = {
    val className = f.getClass.toString
    assert((className contains AnonFunClass), className)
    assert(!(className contains LMFClass), className)
  }

  // Check that we expand the SAM of a type that is specialized.
  // This is an implementation restriction -- the current specialization scheme is not
  // amenable to using LambdaMetaFactory to spin up subclasses.
  // Since the generic method is abstract, and the specialized ones are concrete,
  // specialization is rendered moot because we cannot implement the specialized method
  // with the lambda using LMF.

  // not LMF if specialized at this type
  notLMF((x => x): T[Int])
  // not LMF if specialized at this type (via subclass)
  notLMF((x => x): TInt)
  // LMF ok if not specialized at this type
  LMF((x => x): T[String])

  // traits with a val member also cannot be instantiated by LMF
  val fVal: TWithVal = (x => "a")
  notLMF(fVal)
  assert(fVal.x == 1)

  notLMF((x => "a"): TImpure)
  notLMF((x => "a"): TImpureSuper)

  val fClassParent: TClassParent = x => "a"
  notLMF(fClassParent)
  assert(fClassParent(1) == "a")
}