Skip to content

Commit e47ecb1

Browse files
committed
Merge pull request #496 from dotty-staging/fix-sams-static
Fix #492. Traits that require an outer pointer are not SAMs.
2 parents f1c191a + dee1152 commit e47ecb1

File tree

5 files changed

+32
-7
lines changed

5 files changed

+32
-7
lines changed

src/dotty/tools/dotc/core/Types.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,12 +1788,12 @@ object Types {
17881788
if (false) RefinedType(parent, refinedName, refinedInfo)
17891789
else RefinedType(parent, refinedName, rt => refinedInfo.substSkolem(this, SkolemType(rt)))
17901790
}
1791-
1791+
17921792
/** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */
17931793
def wrapIfMember(parent: Type)(implicit ctx: Context): Type =
17941794
if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo)
17951795
else parent
1796-
1796+
17971797
override def equals(that: Any) = that match {
17981798
case that: RefinedType =>
17991799
this.parent == that.parent &&
@@ -2414,7 +2414,7 @@ object Types {
24142414
selfTypeCache = {
24152415
def fullRef = fullyAppliedRef(cls.typeRef, cls.typeParams)
24162416
val given = givenSelfType
2417-
val raw =
2417+
val raw =
24182418
if (!given.exists) fullRef
24192419
else if (cls is Module) given
24202420
else if (ctx.erasedTypes) fullRef
@@ -2423,7 +2423,7 @@ object Types {
24232423
}
24242424
selfTypeCache
24252425
}
2426-
2426+
24272427
/** The explicitly given self type (self types of modules are assumed to be
24282428
* explcitly given here).
24292429
*/

src/dotty/tools/dotc/transform/ExplicitOuter.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import core.Names._
1313
import core.NameOps._
1414
import ast.Trees._
1515
import SymUtils._
16+
import dotty.tools.dotc.ast.tpd
1617
import dotty.tools.dotc.core.Phases.Phase
1718
import util.Attachment
1819
import collection.mutable
@@ -102,6 +103,15 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf
102103
}
103104
else impl
104105
}
106+
107+
override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
108+
if (tree.tpt ne EmptyTree) {
109+
val cls = tree.tpt.asInstanceOf[TypeTree].tpe.classSymbol
110+
if (cls.exists && hasOuter(cls.asClass))
111+
ctx.error("Not a single abstract method type, requires an outer pointer", tree.pos)
112+
}
113+
tree
114+
}
105115
}
106116

107117
object ExplicitOuter {

test/dotc/tests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class tests extends CompilerTest {
110110
@Test def neg_i50_volatile = compileFile(negDir, "i50-volatile", xerrors = 6)
111111
@Test def neg_t0273_doubledefs = compileFile(negDir, "t0273", xerrors = 1)
112112
@Test def neg_zoo = compileFile(negDir, "zoo", xerrors = 12)
113+
@Test def neg_sam = compileFile(negDir, "sammy_poly", xerrors = 1)
113114
// TODO: this test file doesn't exist (anymore?), remove?
114115
// @Test def neg_t1192_legalPrefix = compileFile(negDir, "t1192", xerrors = 1)
115116

tests/neg/sammy_poly.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// test synthesizeSAMFunction where the sam type is not fully defined
2+
class T {
3+
trait F[T, U] { def apply(x: T): U }
4+
// this is an inner trait, that will recieve an abstract $outer pointer. Not a SAM.
5+
def app[T, U](x: T)(f: F[T, U]): U = f(x)
6+
app(1)(x => List(x))
7+
}

tests/pos/sammy_poly.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
// test synthesizeSAMFunction where the sam type is not fully defined
2+
3+
trait F1[T, U] { def apply(x: T): U }
24
class T {
3-
trait F[T, U] { def apply(x: T): U }
5+
import T._
46
// NOTE: the f(x) desugaring for now assumes the single abstract method is called 'apply'
5-
def app[T, U](x: T)(f: F[T, U]): U = f(x)
6-
app(1)(x => List(x))
7+
def app1[T, U](x: T)(f: F1[T, U]): U = f(x)
8+
def app2[T, U](x: T)(f: F2[T, U]): U = f(x)
9+
app1(1)(x => List(x))
10+
app2(1)(x => List(x))
11+
}
12+
object T{
13+
trait F2[T, U] { def apply(x: T): U }
714
}

0 commit comments

Comments
 (0)