diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index d1c69408281c..ebfbf5926851 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -740,7 +740,10 @@ class Definitions { lazy val TupleType = mkArityArray("scala.Tuple", MaxTupleArity, 2) def FunctionClass(n: Int, isImplicit: Boolean = false)(implicit ctx: Context) = - if (isImplicit) ctx.requiredClass("scala.ImplicitFunction" + n.toString) + if (isImplicit) { + require(n > 0) + ctx.requiredClass("scala.ImplicitFunction" + n.toString) + } else if (n <= MaxImplementedFunctionArity) FunctionClassPerRun()(ctx)(n) else ctx.requiredClass("scala.Function" + n.toString) @@ -773,12 +776,12 @@ class Definitions { /** Is a function class. * - FunctionN for N >= 0 - * - ImplicitFunctionN for N >= 0 + * - ImplicitFunctionN for N > 0 */ def isFunctionClass(cls: Symbol) = scalaClassName(cls).isFunction /** Is an implicit function class. - * - ImplicitFunctionN for N >= 0 + * - ImplicitFunctionN for N > 0 */ def isImplicitFunctionClass(cls: Symbol) = scalaClassName(cls).isImplicitFunction @@ -790,7 +793,7 @@ class Definitions { /** Is a synthetic function class * - FunctionN for N > 22 - * - ImplicitFunctionN for N >= 0 + * - ImplicitFunctionN for N > 0 */ def isSyntheticFunctionClass(cls: Symbol) = scalaClassName(cls).isSyntheticFunction diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index df29a32c523c..5e7b2ec4ab92 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -156,33 +156,36 @@ object NameOps { /** Is a synthetic function name * - N for FunctionN - * - N for ImplicitFunctionN + * - N for ImplicitFunctionN (N >= 1) * - (-1) otherwise */ def functionArity: Int = - functionArityFor(str.Function) max functionArityFor(str.ImplicitFunction) + functionArityFor(str.Function) max { + val n = functionArityFor(str.ImplicitFunction) + if (n == 0) -1 else n + } /** Is a function name * - FunctionN for N >= 0 - * - ImplicitFunctionN for N >= 0 + * - ImplicitFunctionN for N >= 1 * - false otherwise */ def isFunction: Boolean = functionArity >= 0 /** Is a implicit function name - * - ImplicitFunctionN for N >= 0 + * - ImplicitFunctionN for N >= 1 * - false otherwise */ - def isImplicitFunction: Boolean = functionArityFor(str.ImplicitFunction) >= 0 + def isImplicitFunction: Boolean = functionArityFor(str.ImplicitFunction) >= 1 /** Is a synthetic function name * - FunctionN for N > 22 - * - ImplicitFunctionN for N >= 0 + * - ImplicitFunctionN for N >= 1 * - false otherwise */ def isSyntheticFunction: Boolean = { functionArityFor(str.Function) > MaxImplementedFunctionArity || - functionArityFor(str.ImplicitFunction) >= 0 + functionArityFor(str.ImplicitFunction) >= 1 } /** Parsed function arity for function with some specific prefix */ diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 82b7f06e50ff..0c08fcf14770 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -687,7 +687,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context) = track("typedFunction") { val untpd.Function(args, body) = tree if (ctx.mode is Mode.Type) { - val funCls = defn.FunctionClass(args.length, tree.isInstanceOf[untpd.ImplicitFunction]) + val isImplicit = tree match { + case _: untpd.ImplicitFunction => + if (args.length == 0) { + ctx.error(i"implicit function type needs non-empty parameter list", tree.pos) + false + } + else true + case _ => false + } + val funCls = defn.FunctionClass(args.length, isImplicit) typed(cpy.AppliedTypeTree(tree)( untpd.TypeTree(funCls.typeRef), args :+ body), pt) } diff --git a/tests/neg/i2642.scala b/tests/neg/i2642.scala new file mode 100644 index 000000000000..df6e0f599ac1 --- /dev/null +++ b/tests/neg/i2642.scala @@ -0,0 +1,4 @@ +object Foo { + type X = implicit () => Int // error: implicit function needs parameters + def ff: X = () // error: found: Unit, expected: X +}