Skip to content

Commit

Permalink
Also handle SAM functions when adaptiing arity of case lambdas.
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Oct 30, 2015
1 parent 9fbb9c9 commit b80b179
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 14 deletions.
27 changes: 13 additions & 14 deletions src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -502,22 +502,24 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
}

private def decomposeProtoFunction(pt: Type, defaultArity: Int)(implicit ctx: Context): (List[Type], Type) = pt match {
case _ if defn.isFunctionType(pt) =>
(pt.dealias.argInfos.init, pt.dealias.argInfos.last)
case SAMType(meth) =>
val mt @ MethodType(_, paramTypes) = meth.info
(paramTypes, mt.resultType)
case _ =>
(List.range(0, defaultArity) map alwaysWildcardType, WildcardType)
}

def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context) = track("typedFunction") {
val untpd.Function(args, body) = tree
if (ctx.mode is Mode.Type)
typed(cpy.AppliedTypeTree(tree)(
untpd.TypeTree(defn.FunctionClass(args.length).typeRef), args :+ body), pt)
else {
val params = args.asInstanceOf[List[untpd.ValDef]]
val (protoFormals, protoResult): (List[Type], Type) = pt match {
case _ if defn.isFunctionType(pt) =>
(pt.dealias.argInfos.init, pt.dealias.argInfos.last)
case SAMType(meth) =>
val mt @ MethodType(_, paramTypes) = meth.info
(paramTypes, mt.resultType)
case _ =>
(params map alwaysWildcardType, WildcardType)
}
val (protoFormals, protoResult) = decomposeProtoFunction(pt, params.length)

def refersTo(arg: untpd.Tree, param: untpd.ValDef): Boolean = arg match {
case Ident(name) => name == param.name
Expand Down Expand Up @@ -629,11 +631,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context) = track("typedMatch") {
tree.selector match {
case EmptyTree =>
val arity = pt match {
case defn.FunctionType(args, _) => args.length
case _ => 1
}
typed(desugar.makeCaseLambda(tree.cases, arity) withPos tree.pos, pt)
val (protoFormals, _) = decomposeProtoFunction(pt, 1)
typed(desugar.makeCaseLambda(tree.cases, protoFormals.length) withPos tree.pos, pt)
case _ =>
val sel1 = typedExpr(tree.selector)
val selType = widenForMatchSelector(
Expand Down
6 changes: 6 additions & 0 deletions tests/pos/i873.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
object Test {
def call(k: (Int, Int) => Unit): Unit = ???
def test = call({ case (x, y) => ()})

trait X extends Function1[Int, String]
implicit def f2x(f: Function1[Int, String]): X = ???
({case _ if "".isEmpty => ""} : X) // allowed, implicit view used to adapt

// ({case _ if "".isEmpty => 0} : X) // expected String, found Int
}

0 comments on commit b80b179

Please sign in to comment.