Skip to content

Fix #492. Traits that require an outer pointer are not SAMs. #496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 23, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1788,12 +1788,12 @@ object Types {
if (false) RefinedType(parent, refinedName, refinedInfo)
else RefinedType(parent, refinedName, rt => refinedInfo.substSkolem(this, SkolemType(rt)))
}

/** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */
def wrapIfMember(parent: Type)(implicit ctx: Context): Type =
if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo)
else parent

override def equals(that: Any) = that match {
case that: RefinedType =>
this.parent == that.parent &&
Expand Down Expand Up @@ -2414,7 +2414,7 @@ object Types {
selfTypeCache = {
def fullRef = fullyAppliedRef(cls.typeRef, cls.typeParams)
val given = givenSelfType
val raw =
val raw =
if (!given.exists) fullRef
else if (cls is Module) given
else if (ctx.erasedTypes) fullRef
Expand All @@ -2423,7 +2423,7 @@ object Types {
}
selfTypeCache
}

/** The explicitly given self type (self types of modules are assumed to be
* explcitly given here).
*/
Expand Down
10 changes: 10 additions & 0 deletions src/dotty/tools/dotc/transform/ExplicitOuter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import core.Names._
import core.NameOps._
import ast.Trees._
import SymUtils._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Phases.Phase
import util.Attachment
import collection.mutable
Expand Down Expand Up @@ -102,6 +103,15 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf
}
else impl
}

override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
if (tree.tpt ne EmptyTree) {
val cls = tree.tpt.asInstanceOf[TypeTree].tpe.classSymbol
if (cls.exists && hasOuter(cls.asClass))
ctx.error("Not a single abstract method type, requires an outer pointer", tree.pos)
}
tree
}
}

object ExplicitOuter {
Expand Down
1 change: 1 addition & 0 deletions test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class tests extends CompilerTest {
@Test def neg_i50_volatile = compileFile(negDir, "i50-volatile", xerrors = 6)
@Test def neg_t0273_doubledefs = compileFile(negDir, "t0273", xerrors = 1)
@Test def neg_zoo = compileFile(negDir, "zoo", xerrors = 12)
@Test def neg_sam = compileFile(negDir, "sammy_poly", xerrors = 1)
// TODO: this test file doesn't exist (anymore?), remove?
// @Test def neg_t1192_legalPrefix = compileFile(negDir, "t1192", xerrors = 1)

Expand Down
7 changes: 7 additions & 0 deletions tests/neg/sammy_poly.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// test synthesizeSAMFunction where the sam type is not fully defined
class T {
trait F[T, U] { def apply(x: T): U }
// this is an inner trait, that will recieve an abstract $outer pointer. Not a SAM.
def app[T, U](x: T)(f: F[T, U]): U = f(x)
app(1)(x => List(x))
}
13 changes: 10 additions & 3 deletions tests/pos/sammy_poly.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// test synthesizeSAMFunction where the sam type is not fully defined

trait F1[T, U] { def apply(x: T): U }
class T {
trait F[T, U] { def apply(x: T): U }
import T._
// NOTE: the f(x) desugaring for now assumes the single abstract method is called 'apply'
def app[T, U](x: T)(f: F[T, U]): U = f(x)
app(1)(x => List(x))
def app1[T, U](x: T)(f: F1[T, U]): U = f(x)
def app2[T, U](x: T)(f: F2[T, U]): U = f(x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be T.F2 instead of F2, or add import T._

app1(1)(x => List(x))
app2(1)(x => List(x))
}
object T{
trait F2[T, U] { def apply(x: T): U }
}