Skip to content

Commit c8411af

Browse files
authored
Merge pull request #3402 from dotty-staging/fix-#3246
Fix #3246: Refine handling of postfix _ for non-functions
2 parents 3a72da6 + 29515c7 commit c8411af

File tree

6 files changed

+39
-10
lines changed

6 files changed

+39
-10
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
527527
def unapply(tree: Tree): Option[(List[Tree], Tree, Tree)] = tree match {
528528
case Block(_, expr) => unapply(expr)
529529
case Closure(env, meth, tpt) => Some(env, meth, tpt)
530+
case Typed(expr, _) => unapply(expr)
530531
case _ => None
531532
}
532533
}

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,17 +1548,21 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
15481548
def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(implicit ctx: Context): Tree = {
15491549
val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree
15501550
val pt1 = if (defn.isFunctionType(pt)) pt else AnyFunctionProto
1551-
var res = typed(qual, pt1)
1552-
if (pt1.eq(AnyFunctionProto) && !defn.isFunctionClass(res.tpe.classSymbol)) {
1553-
ctx.errorOrMigrationWarning(OnlyFunctionsCanBeFollowedByUnderscore(res.tpe), tree.pos)
1554-
if (ctx.scala2Mode) {
1555-
// Under -rewrite, patch `x _` to `(() => x)`
1556-
patch(Position(tree.pos.start), "(() => ")
1557-
patch(Position(qual.pos.end, tree.pos.end), ")")
1558-
res = typed(untpd.Function(Nil, untpd.TypedSplice(res)))
1559-
}
1551+
val nestedCtx = ctx.fresh.setNewTyperState()
1552+
val res = typed(qual, pt1)(nestedCtx)
1553+
res match {
1554+
case res @ closure(_, _, _) =>
1555+
case _ =>
1556+
ctx.errorOrMigrationWarning(OnlyFunctionsCanBeFollowedByUnderscore(res.tpe), tree.pos)
1557+
if (ctx.scala2Mode) {
1558+
// Under -rewrite, patch `x _` to `(() => x)`
1559+
patch(Position(tree.pos.start), "(() => ")
1560+
patch(Position(qual.pos.end, tree.pos.end), ")")
1561+
return typed(untpd.Function(Nil, qual), pt)
1562+
}
15601563
}
1561-
else if (ctx.settings.strict.value) {
1564+
nestedCtx.typerState.commit()
1565+
if (ctx.settings.strict.value) {
15621566
lazy val (prefix, suffix) = res match {
15631567
case Block(mdef @ DefDef(_, _, vparams :: Nil, _, _) :: Nil, _: Closure) =>
15641568
val arity = vparams.length

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class CompilationTests extends ParallelTesting {
182182
compileFile("../tests/neg/tailcall/tailrec.scala", defaultOptions) +
183183
compileFile("../tests/neg/tailcall/tailrec-2.scala", defaultOptions) +
184184
compileFile("../tests/neg/tailcall/tailrec-3.scala", defaultOptions) +
185+
compileFile("../tests/neg/i3246.scala", scala2Mode) +
185186
compileDir("../tests/neg/typedIdents", defaultOptions)
186187
}.checkExpectedErrors()
187188

tests/neg/i3246.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Test {
2+
def foo(x: Int) = 1
3+
val bar: () => Int = foo _ // error: type mismatch
4+
}

tests/pos-scala2/i3246.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Test {
2+
def foo(x: => Int) = bar(x _)
3+
def bar(x: () => Int) = ???
4+
def baz = 1
5+
def bam: () => Int = baz _
6+
def ban: () => Int = 1 _
7+
8+
def titi(fun: () => Unit) = ???
9+
def toto(fun: => Int) = titi(fun _)
10+
titi(1 _) // rejected by scalac
11+
}

tests/pos/i3246.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Test {
2+
class A {
3+
type T = Int
4+
def f(x: T): T = ???
5+
}
6+
def a: A = new A
7+
val f = a.f _
8+
}

0 commit comments

Comments
 (0)