diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index e1d96af39e33..7d8786bd5a4a 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -114,10 +114,11 @@ class Definitions { val cls = denot.asClass.classSymbol val decls = newScope val arity = name.functionArity + val paramNamePrefix = tpnme.scala_ ++ str.NAME_JOIN ++ name ++ str.EXPAND_SEPARATOR val argParams = - for (i <- List.range(0, arity)) yield - enterTypeParam(cls, name ++ "$T" ++ i.toString, Contravariant, decls) - val resParam = enterTypeParam(cls, name ++ "$R", Covariant, decls) + for (i <- List.range(1, arity + 1)) yield + enterTypeParam(cls, paramNamePrefix ++ "T" ++ i.toString, Contravariant, decls) + val resParam = enterTypeParam(cls, paramNamePrefix ++ "R", Covariant, decls) val (methodType, parentTraits) = if (name.firstPart.startsWith(str.ImplicitFunction)) { val superTrait = diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index f63cba3f1f7b..29e9d3813abf 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -8,6 +8,7 @@ import TreeTransforms._ import SymUtils._ import ast.untpd import ast.Trees._ +import dotty.tools.dotc.util.Positions.Position /** Expand SAM closures that cannot be represented by the JVM as lambdas to anonymous classes. * These fall into five categories @@ -34,10 +35,13 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer => tpt.tpe match { case NoType => tree // it's a plain function case tpe @ SAMType(_) if tpe.isRef(defn.PartialFunctionClass) => + checkRefinements(tpe, fn.pos) toPartialFunction(tree) case tpe @ SAMType(_) if isPlatformSam(tpe.classSymbol.asClass) => + checkRefinements(tpe, fn.pos) tree case tpe => + checkRefinements(tpe, fn.pos) val Seq(samDenot) = tpe.abstractTermMembers.filter(!_.symbol.isSuperAccessor) cpy.Block(tree)(stats, AnonClass(tpe :: Nil, fn.symbol.asTerm :: Nil, samDenot.symbol.asTerm.name :: Nil)) @@ -83,4 +87,13 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer => val anonCls = AnonClass(tpt.tpe :: Nil, List(applyFn, isDefinedAtFn), List(nme.apply, nme.isDefinedAt)) cpy.Block(tree)(List(applyDef, isDefinedAtDef), anonCls) } + + private def checkRefinements(tpe: Type, pos: Position)(implicit ctx: Context): Unit = tpe match { + case RefinedType(parent, name, _) => + if (name.isTermName && tpe.member(name).symbol.ownersIterator.isEmpty) // if member defined in the refinement + ctx.error("Lambda does not define " + name, pos) + checkRefinements(parent, pos) + case _ => + } + } diff --git a/tests/neg/i2539.scala b/tests/neg/i2539.scala new file mode 100644 index 000000000000..7f80d0d4d7ad --- /dev/null +++ b/tests/neg/i2539.scala @@ -0,0 +1,17 @@ +object Foo { + val f0: Function0[Int]{ def foo(): Int } = () => 42 // error + + val f1: Function1[Int, Int]{ def foo(): Int } = x1 => 42 // error + + val f26: Function26[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]{ def foo(): Int } = + (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26) => 42 // error + + val if1: ImplicitFunction1[Int, Int]{ def foo(): Int } = implicit x1 => 42 // error + + abstract class Fun0[X] extends Function0[X] + val fun0a: Fun0[Int] = () => 42 + val fun0b: Fun0[Int] { def foo(): Int } = () => 42 // error + + val pf: PartialFunction[Int, Int]{ def foo(): Int } = { case x1 => 42 } // error + +}