From 1e0d6be62aaf7a28cb8c3fdf6a08ec9d6e52bea1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 26 May 2017 14:47:28 +0200 Subject: [PATCH 1/3] Make synthetic function type members match non synthetic --- compiler/src/dotty/tools/dotc/core/Definitions.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 = From 157b3d4b6c60e26b4ba10d62175121e587ca4a13 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 26 May 2017 14:59:29 +0200 Subject: [PATCH 2/3] Fix #2539: Error when adding refined terms to SAMs --- .../dotty/tools/dotc/transform/ExpandSAMs.scala | 12 ++++++++++++ tests/neg/i2539.scala | 15 +++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/neg/i2539.scala diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index f63cba3f1f7b..9c3f847c8e8f 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 @@ -36,8 +37,10 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer => case tpe @ SAMType(_) if tpe.isRef(defn.PartialFunctionClass) => 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 +86,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(s"Cannot refine $name on a lambda", pos) + checkRefinements(parent, pos) + case _ => + } + } diff --git a/tests/neg/i2539.scala b/tests/neg/i2539.scala new file mode 100644 index 000000000000..0a49a310dc5c --- /dev/null +++ b/tests/neg/i2539.scala @@ -0,0 +1,15 @@ +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 + +} From a0ec7b2e872490185018d0cd54df8dad336f6ffb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 26 May 2017 15:13:55 +0200 Subject: [PATCH 3/3] Add error for partial functions with refined terms --- compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala | 3 ++- tests/neg/i2539.scala | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 9c3f847c8e8f..29e9d3813abf 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -35,6 +35,7 @@ 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) @@ -90,7 +91,7 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer => 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(s"Cannot refine $name on a lambda", pos) + ctx.error("Lambda does not define " + name, pos) checkRefinements(parent, pos) case _ => } diff --git a/tests/neg/i2539.scala b/tests/neg/i2539.scala index 0a49a310dc5c..7f80d0d4d7ad 100644 --- a/tests/neg/i2539.scala +++ b/tests/neg/i2539.scala @@ -12,4 +12,6 @@ object Foo { 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 + }