Skip to content

Commit f97f3ce

Browse files
Improve missing argument list error (#17126)
Fixes #17123
2 parents b1470fa + 3420f1b commit f97f3ce

File tree

13 files changed

+187
-24
lines changed

13 files changed

+187
-24
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,12 @@ object Contexts {
444444
def useColors: Boolean =
445445
base.settings.color.value == "always"
446446

447+
def withColors: FreshContext =
448+
fresh.setSetting(ctx.settings.color, "always")
449+
450+
def withoutColors: FreshContext =
451+
fresh.setSetting(ctx.settings.color, "never")
452+
447453
/** Is the explicit nulls option set? */
448454
def explicitNulls: Boolean = base.settings.YexplicitNulls.value
449455

compiler/src/dotty/tools/dotc/inlines/Inlines.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,7 @@ object Inlines:
381381

382382
/** Expand call to scala.compiletime.codeOf */
383383
def codeOf(arg: Tree, pos: SrcPos)(using Context): Tree =
384-
val ctx1 = ctx.fresh.setSetting(ctx.settings.color, "never")
385-
Literal(Constant(arg.show(using ctx1))).withSpan(pos.span)
384+
Literal(Constant(arg.show(using ctx.withoutColors))).withSpan(pos.span)
386385
end Intrinsics
387386

388387
/** Produces an inlined version of `call` via its `inlined` method.

compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
191191
case ValueDiscardingID // errorNumber 175
192192
case UnusedNonUnitValueID // errorNumber 176
193193
case ConstrProxyShadowsID // errorNumber 177
194+
case MissingArgumentListID // errorNumber: 178
194195

195196
def errorNumber = ordinal - 1
196197

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,16 @@ class MissingArgument(pname: Name, methString: String)(using Context)
15011501
else s"missing argument for parameter $pname of $methString"
15021502
def explain(using Context) = ""
15031503

1504+
class MissingArgumentList(method: String, sym: Symbol)(using Context)
1505+
extends TypeMsg(MissingArgumentListID) {
1506+
def msg(using Context) =
1507+
val symDcl = if sym.exists then "\n\n " + hl(sym.showDcl(using ctx.withoutColors)) else ""
1508+
i"missing argument list for $method$symDcl"
1509+
def explain(using Context) = {
1510+
i"""Unapplied methods are only converted to functions when a function type is expected."""
1511+
}
1512+
}
1513+
15041514
class DoesNotConformToBound(tpe: Type, which: String, bound: Type)(using Context)
15051515
extends TypeMismatchMsg(
15061516
if which == "lower" then bound else tpe,

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,24 @@ object ErrorReporting {
4141
errorType(WrongNumberOfTypeArgs(fntpe, expectedArgs, actual), pos)
4242

4343
def missingArgs(tree: Tree, mt: Type)(using Context): Unit =
44+
def isCallableWithoutArgumentsLists(mt: Type): Boolean = mt match
45+
case pt: PolyType => isCallableWithoutArgumentsLists(pt.resType)
46+
case mt: MethodType if mt.isImplicitMethod => isCallableWithoutArgumentsLists(mt.resType)
47+
case mt: MethodType => false
48+
case _ => true
49+
def isCallableWithSingleEmptyArgumentList(mt: Type): Boolean =
50+
mt match
51+
case mt: MethodType if mt.paramNames.isEmpty => isCallableWithoutArgumentsLists(mt.resType)
52+
case mt: MethodType if mt.isImplicitMethod => isCallableWithSingleEmptyArgumentList(mt.resType)
53+
case pt: PolyType => isCallableWithSingleEmptyArgumentList(pt.resType)
54+
case _ => false
4455
val meth = err.exprStr(methPart(tree))
45-
mt match
46-
case mt: MethodType if mt.paramNames.isEmpty =>
47-
report.error(MissingEmptyArgumentList(meth), tree.srcPos)
48-
case _ =>
49-
report.error(em"missing arguments for $meth", tree.srcPos)
56+
val info = if tree.symbol.exists then tree.symbol.info else mt
57+
if isCallableWithSingleEmptyArgumentList(info) then
58+
report.error(MissingEmptyArgumentList(meth), tree.srcPos)
59+
else
60+
report.error(MissingArgumentList(meth, tree.symbol), tree.srcPos)
61+
5062

5163
def matchReductionAddendum(tps: Type*)(using Context): String =
5264
val collectMatchTrace = new TypeAccumulator[String]:

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3080,7 +3080,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
30803080

30813081
lazy val ConstantCode: Printer[Constant] = new Printer[Constant]:
30823082
def show(const: Constant): String =
3083-
const.show(using ctx.fresh.setSetting(ctx.settings.color, "never"))
3083+
const.show(using ctx.withoutColors)
30843084

30853085
lazy val ConstantStructure: Printer[Constant] = new Printer[Constant]:
30863086
def show(const: Constant): String =

compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ class SyntaxHighlightingTests extends DottyTest {
1212
import SyntaxHighlighting._
1313

1414
private def test(source: String, expected: String): Unit = {
15-
val testCtx = ctx.fresh.setSetting(ctx.settings.color, "always")
16-
val highlighted = SyntaxHighlighting.highlight(source)(using testCtx)
15+
val highlighted = SyntaxHighlighting.highlight(source)(using ctx.withColors)
1716
.replace(NoColor, ">")
1817
.replace(CommentColor, "<C|")
1918
.replace(KeywordColor, "<K|")

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ trait ErrorMessagesTest extends DottyTest {
1212
protected def newContext = {
1313
val rep = new StoreReporter(null)
1414
with UniqueMessagePositions with HideNonSensicalMessages
15-
initialCtx.setReporter(rep).setSetting(ctx.settings.color, "never")
15+
initialCtx.setReporter(rep).withoutColors
1616
}
1717

1818
class Report(messages: List[Message], ictx: Context) {

tests/neg/i16820.check

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
1-
-- Error: tests/neg/i16820.scala:5:11 ----------------------------------------------------------------------------------
1+
-- [E178] Type Error: tests/neg/i16820.scala:5:11 ----------------------------------------------------------------------
22
5 | val x1 = f // error
33
| ^
4-
| missing arguments for method f in object Test
4+
| missing argument list for method f in object Test
5+
|
6+
| def f(xs: Int*): Int
7+
|
8+
| longer explanation available when compiling with `-explain`
59
-- [E100] Syntax Error: tests/neg/i16820.scala:6:11 --------------------------------------------------------------------
610
6 | val x2 = g // error
711
| ^
812
| method g in object Test must be called with () argument
913
|
1014
| longer explanation available when compiling with `-explain`
11-
-- Error: tests/neg/i16820.scala:7:40 ----------------------------------------------------------------------------------
15+
-- [E178] Type Error: tests/neg/i16820.scala:7:40 ----------------------------------------------------------------------
1216
7 | val x3 = java.nio.file.Paths.get(".").toRealPath // error
1317
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14-
| missing arguments for method toRealPath in trait Path
15-
-- Error: tests/neg/i16820.scala:11:14 ---------------------------------------------------------------------------------
18+
| missing argument list for method toRealPath in trait Path
19+
|
20+
| def toRealPath(x$0: java.nio.file.LinkOption*): java.nio.file.Path
21+
|
22+
| longer explanation available when compiling with `-explain`
23+
-- [E178] Type Error: tests/neg/i16820.scala:11:14 ---------------------------------------------------------------------
1624
11 |def test = Foo(3) // error
1725
| ^^^^^^
18-
| missing arguments for method apply in object Foo
26+
| missing argument list for method apply in object Foo
27+
|
28+
| def apply(x: Int)(xs: String*): Foo
29+
|
30+
| longer explanation available when compiling with `-explain`

tests/neg/i17123.check

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
-- [E100] Syntax Error: tests/neg/i17123.scala:7:2 ---------------------------------------------------------------------
2+
7 | m1 // error
3+
| ^^
4+
| method m1 in object ConfusingErrorMessage must be called with () argument
5+
|
6+
| longer explanation available when compiling with `-explain`
7+
-- [E178] Type Error: tests/neg/i17123.scala:9:2 -----------------------------------------------------------------------
8+
9 | m2 // error
9+
| ^^
10+
| missing argument list for method m2 in object ConfusingErrorMessage
11+
|
12+
| def m2()(): Unit
13+
|
14+
| longer explanation available when compiling with `-explain`
15+
-- [E178] Type Error: tests/neg/i17123.scala:10:4 ----------------------------------------------------------------------
16+
10 | m2() // error
17+
| ^^^^
18+
| missing argument list for method m2 in object ConfusingErrorMessage
19+
|
20+
| def m2()(): Unit
21+
|
22+
| longer explanation available when compiling with `-explain`
23+
-- [E178] Type Error: tests/neg/i17123.scala:11:2 ----------------------------------------------------------------------
24+
11 | m3 // error
25+
| ^^
26+
| missing argument list for method m3 in object ConfusingErrorMessage
27+
|
28+
| def m3()()(): Unit
29+
|
30+
| longer explanation available when compiling with `-explain`
31+
-- [E178] Type Error: tests/neg/i17123.scala:12:4 ----------------------------------------------------------------------
32+
12 | m3() // error
33+
| ^^^^
34+
| missing argument list for method m3 in object ConfusingErrorMessage
35+
|
36+
| def m3()()(): Unit
37+
|
38+
| longer explanation available when compiling with `-explain`
39+
-- [E178] Type Error: tests/neg/i17123.scala:13:6 ----------------------------------------------------------------------
40+
13 | m3()() // error
41+
| ^^^^^^
42+
| missing argument list for method m3 in object ConfusingErrorMessage
43+
|
44+
| def m3()()(): Unit
45+
|
46+
| longer explanation available when compiling with `-explain`
47+
-- [E178] Type Error: tests/neg/i17123.scala:15:2 ----------------------------------------------------------------------
48+
15 | f3 // error
49+
| ^^
50+
| missing argument list for method f3 in object ConfusingErrorMessage
51+
|
52+
| def f3()(i: Int)(): Unit
53+
|
54+
| longer explanation available when compiling with `-explain`
55+
-- [E178] Type Error: tests/neg/i17123.scala:16:2 ----------------------------------------------------------------------
56+
16 | f3() // error
57+
| ^^^^
58+
| missing argument list for method f3 in object ConfusingErrorMessage
59+
|
60+
| def f3()(i: Int)(): Unit
61+
|
62+
| longer explanation available when compiling with `-explain`
63+
-- [E178] Type Error: tests/neg/i17123.scala:17:6 ----------------------------------------------------------------------
64+
17 | f3()(2) // error
65+
| ^^^^^^^
66+
| missing argument list for method f3 in object ConfusingErrorMessage
67+
|
68+
| def f3()(i: Int)(): Unit
69+
|
70+
| longer explanation available when compiling with `-explain`
71+
-- [E178] Type Error: tests/neg/i17123.scala:19:2 ----------------------------------------------------------------------
72+
19 | i3 // error
73+
| ^^
74+
| missing argument list for method i3 in object ConfusingErrorMessage
75+
|
76+
| def i3()(using d: DummyImplicit)(): Unit
77+
|
78+
| longer explanation available when compiling with `-explain`
79+
-- [E178] Type Error: tests/neg/i17123.scala:20:2 ----------------------------------------------------------------------
80+
20 | i3() // error
81+
| ^^^^
82+
| missing argument list for method i3 in object ConfusingErrorMessage
83+
|
84+
| def i3()(using d: DummyImplicit)(): Unit
85+
|
86+
| longer explanation available when compiling with `-explain`

tests/neg/i17123.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
object ConfusingErrorMessage {
2+
def m1() = ()
3+
def m2()() = ()
4+
def m3()()() = ()
5+
def f3()(i: Int)() = ()
6+
def i3()(using d: DummyImplicit)() = ()
7+
m1 // error
8+
m1()
9+
m2 // error
10+
m2() // error
11+
m3 // error
12+
m3() // error
13+
m3()() // error
14+
m3()()()
15+
f3 // error
16+
f3() // error
17+
f3()(2) // error
18+
f3()(2)()
19+
i3 // error
20+
i3() // error
21+
i3()()
22+
}

tests/neg/i7816.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
object A {
22
def f()(>) = ??? // error
3-
import f.NonExistent // error
3+
import f.NonExistent
44
}

tests/neg/indent-colons.check

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,31 @@
4747
| Not found: file
4848
|
4949
| longer explanation available when compiling with `-explain`
50-
-- Error: tests/neg/indent-colons.scala:5:2 ----------------------------------------------------------------------------
50+
-- [E178] Type Error: tests/neg/indent-colons.scala:5:2 ----------------------------------------------------------------
5151
5 | tryEither: // error
5252
| ^^^^^^^^^
53-
| missing arguments for method tryEither
54-
-- Error: tests/neg/indent-colons.scala:11:2 ---------------------------------------------------------------------------
53+
| missing argument list for method tryEither
54+
|
55+
| def tryEither[T](x: T)(y: Int => T): T
56+
|
57+
| where: T is a type variable
58+
|
59+
| longer explanation available when compiling with `-explain`
60+
-- [E178] Type Error: tests/neg/indent-colons.scala:11:2 ---------------------------------------------------------------
5561
11 | tryEither: // error
5662
| ^^^^^^^^^
57-
| missing arguments for method tryEither
58-
-- Error: tests/neg/indent-colons.scala:18:2 ---------------------------------------------------------------------------
63+
| missing argument list for method tryEither
64+
|
65+
| def tryEither[T](x: T)(y: Int => T): T
66+
|
67+
| where: T is a type variable
68+
|
69+
| longer explanation available when compiling with `-explain`
70+
-- [E178] Type Error: tests/neg/indent-colons.scala:18:2 ---------------------------------------------------------------
5971
18 | Some(3).fold: // error
6072
| ^^^^^^^^^^^^
61-
| missing arguments for method fold in class Option
73+
| missing argument list for method fold in class Option
74+
|
75+
| final def fold[B](ifEmpty: => B)(f: A => B): B
76+
|
77+
| longer explanation available when compiling with `-explain`

0 commit comments

Comments
 (0)