Skip to content

Commit cf346d4

Browse files
committed
Fix #2642: Disallow nullary implicit function types
1 parent ddd2a1b commit cf346d4

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,10 @@ class Definitions {
740740
lazy val TupleType = mkArityArray("scala.Tuple", MaxTupleArity, 2)
741741

742742
def FunctionClass(n: Int, isImplicit: Boolean = false)(implicit ctx: Context) =
743-
if (isImplicit) ctx.requiredClass("scala.ImplicitFunction" + n.toString)
743+
if (isImplicit) {
744+
require(n > 0)
745+
ctx.requiredClass("scala.ImplicitFunction" + n.toString)
746+
}
744747
else if (n <= MaxImplementedFunctionArity) FunctionClassPerRun()(ctx)(n)
745748
else ctx.requiredClass("scala.Function" + n.toString)
746749

@@ -773,12 +776,12 @@ class Definitions {
773776

774777
/** Is a function class.
775778
* - FunctionN for N >= 0
776-
* - ImplicitFunctionN for N >= 0
779+
* - ImplicitFunctionN for N > 0
777780
*/
778781
def isFunctionClass(cls: Symbol) = scalaClassName(cls).isFunction
779782

780783
/** Is an implicit function class.
781-
* - ImplicitFunctionN for N >= 0
784+
* - ImplicitFunctionN for N > 0
782785
*/
783786
def isImplicitFunctionClass(cls: Symbol) = scalaClassName(cls).isImplicitFunction
784787

@@ -790,7 +793,7 @@ class Definitions {
790793

791794
/** Is a synthetic function class
792795
* - FunctionN for N > 22
793-
* - ImplicitFunctionN for N >= 0
796+
* - ImplicitFunctionN for N > 0
794797
*/
795798
def isSyntheticFunctionClass(cls: Symbol) = scalaClassName(cls).isSyntheticFunction
796799

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
687687
def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context) = track("typedFunction") {
688688
val untpd.Function(args, body) = tree
689689
if (ctx.mode is Mode.Type) {
690-
val funCls = defn.FunctionClass(args.length, tree.isInstanceOf[untpd.ImplicitFunction])
690+
val isImplicit = tree match {
691+
case _: untpd.ImplicitFunction =>
692+
if (args.length == 0) {
693+
ctx.error(i"implicit function type needs non-empty parameter list", tree.pos)
694+
false
695+
}
696+
else true
697+
case _ => false
698+
}
699+
val funCls = defn.FunctionClass(args.length, isImplicit)
691700
typed(cpy.AppliedTypeTree(tree)(
692701
untpd.TypeTree(funCls.typeRef), args :+ body), pt)
693702
}

tests/neg/i2642.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object Foo {
2+
type X = implicit () => Int // error: implicit function needs parameters
3+
def ff: X = () // error: found: Unit, expected: X
4+
}

0 commit comments

Comments
 (0)