Skip to content

Improve missing argument list error #17126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,12 @@ object Contexts {
def useColors: Boolean =
base.settings.color.value == "always"

def withColors: FreshContext =
fresh.setSetting(ctx.settings.color, "always")

def withoutColors: FreshContext =
fresh.setSetting(ctx.settings.color, "never")

/** Is the explicit nulls option set? */
def explicitNulls: Boolean = base.settings.YexplicitNulls.value

Expand Down
3 changes: 1 addition & 2 deletions compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,7 @@ object Inlines:

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

/** Produces an inlined version of `call` via its `inlined` method.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
case ValueDiscardingID // errorNumber 175
case UnusedNonUnitValueID // errorNumber 176
case ConstrProxyShadowsID // errorNumber 177
case MissingArgumentListID // errorNumber: 178

def errorNumber = ordinal - 1

Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,16 @@ class MissingArgument(pname: Name, methString: String)(using Context)
else s"missing argument for parameter $pname of $methString"
def explain(using Context) = ""

class MissingArgumentList(method: String, sym: Symbol)(using Context)
extends TypeMsg(MissingArgumentListID) {
def msg(using Context) =
val symDcl = if sym.exists then "\n\n " + hl(sym.showDcl(using ctx.withoutColors)) else ""
i"missing argument list for $method$symDcl"
def explain(using Context) = {
i"""Unapplied methods are only converted to functions when a function type is expected."""
}
}

class DoesNotConformToBound(tpe: Type, which: String, bound: Type)(using Context)
extends TypeMismatchMsg(
if which == "lower" then bound else tpe,
Expand Down
22 changes: 17 additions & 5 deletions compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,24 @@ object ErrorReporting {
errorType(WrongNumberOfTypeArgs(fntpe, expectedArgs, actual), pos)

def missingArgs(tree: Tree, mt: Type)(using Context): Unit =
def isCallableWithoutArgumentsLists(mt: Type): Boolean = mt match
case pt: PolyType => isCallableWithoutArgumentsLists(pt.resType)
case mt: MethodType if mt.isImplicitMethod => isCallableWithoutArgumentsLists(mt.resType)
case mt: MethodType => false
case _ => true
def isCallableWithSingleEmptyArgumentList(mt: Type): Boolean =
mt match
case mt: MethodType if mt.paramNames.isEmpty => isCallableWithoutArgumentsLists(mt.resType)
case mt: MethodType if mt.isImplicitMethod => isCallableWithSingleEmptyArgumentList(mt.resType)
case pt: PolyType => isCallableWithSingleEmptyArgumentList(pt.resType)
case _ => false
val meth = err.exprStr(methPart(tree))
mt match
case mt: MethodType if mt.paramNames.isEmpty =>
report.error(MissingEmptyArgumentList(meth), tree.srcPos)
case _ =>
report.error(em"missing arguments for $meth", tree.srcPos)
val info = if tree.symbol.exists then tree.symbol.info else mt
if isCallableWithSingleEmptyArgumentList(info) then
report.error(MissingEmptyArgumentList(meth), tree.srcPos)
else
report.error(MissingArgumentList(meth, tree.symbol), tree.srcPos)


def matchReductionAddendum(tps: Type*)(using Context): String =
val collectMatchTrace = new TypeAccumulator[String]:
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3080,7 +3080,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler

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

lazy val ConstantStructure: Printer[Constant] = new Printer[Constant]:
def show(const: Constant): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ class SyntaxHighlightingTests extends DottyTest {
import SyntaxHighlighting._

private def test(source: String, expected: String): Unit = {
val testCtx = ctx.fresh.setSetting(ctx.settings.color, "always")
val highlighted = SyntaxHighlighting.highlight(source)(using testCtx)
val highlighted = SyntaxHighlighting.highlight(source)(using ctx.withColors)
.replace(NoColor, ">")
.replace(CommentColor, "<C|")
.replace(KeywordColor, "<K|")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait ErrorMessagesTest extends DottyTest {
protected def newContext = {
val rep = new StoreReporter(null)
with UniqueMessagePositions with HideNonSensicalMessages
initialCtx.setReporter(rep).setSetting(ctx.settings.color, "never")
initialCtx.setReporter(rep).withoutColors
}

class Report(messages: List[Message], ictx: Context) {
Expand Down
24 changes: 18 additions & 6 deletions tests/neg/i16820.check
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
-- Error: tests/neg/i16820.scala:5:11 ----------------------------------------------------------------------------------
-- [E178] Type Error: tests/neg/i16820.scala:5:11 ----------------------------------------------------------------------
5 | val x1 = f // error
| ^
| missing arguments for method f in object Test
| missing argument list for method f in object Test
|
| def f(xs: Int*): Int
|
| longer explanation available when compiling with `-explain`
-- [E100] Syntax Error: tests/neg/i16820.scala:6:11 --------------------------------------------------------------------
6 | val x2 = g // error
| ^
| method g in object Test must be called with () argument
|
| longer explanation available when compiling with `-explain`
-- Error: tests/neg/i16820.scala:7:40 ----------------------------------------------------------------------------------
-- [E178] Type Error: tests/neg/i16820.scala:7:40 ----------------------------------------------------------------------
7 | val x3 = java.nio.file.Paths.get(".").toRealPath // error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| missing arguments for method toRealPath in trait Path
-- Error: tests/neg/i16820.scala:11:14 ---------------------------------------------------------------------------------
| missing argument list for method toRealPath in trait Path
|
| def toRealPath(x$0: java.nio.file.LinkOption*): java.nio.file.Path
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i16820.scala:11:14 ---------------------------------------------------------------------
11 |def test = Foo(3) // error
| ^^^^^^
| missing arguments for method apply in object Foo
| missing argument list for method apply in object Foo
|
| def apply(x: Int)(xs: String*): Foo
|
| longer explanation available when compiling with `-explain`
86 changes: 86 additions & 0 deletions tests/neg/i17123.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
-- [E100] Syntax Error: tests/neg/i17123.scala:7:2 ---------------------------------------------------------------------
7 | m1 // error
| ^^
| method m1 in object ConfusingErrorMessage must be called with () argument
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:9:2 -----------------------------------------------------------------------
9 | m2 // error
| ^^
| missing argument list for method m2 in object ConfusingErrorMessage
|
| def m2()(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:10:4 ----------------------------------------------------------------------
10 | m2() // error
| ^^^^
| missing argument list for method m2 in object ConfusingErrorMessage
|
| def m2()(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:11:2 ----------------------------------------------------------------------
11 | m3 // error
| ^^
| missing argument list for method m3 in object ConfusingErrorMessage
|
| def m3()()(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:12:4 ----------------------------------------------------------------------
12 | m3() // error
| ^^^^
| missing argument list for method m3 in object ConfusingErrorMessage
|
| def m3()()(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:13:6 ----------------------------------------------------------------------
13 | m3()() // error
| ^^^^^^
| missing argument list for method m3 in object ConfusingErrorMessage
|
| def m3()()(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:15:2 ----------------------------------------------------------------------
15 | f3 // error
| ^^
| missing argument list for method f3 in object ConfusingErrorMessage
|
| def f3()(i: Int)(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:16:2 ----------------------------------------------------------------------
16 | f3() // error
| ^^^^
| missing argument list for method f3 in object ConfusingErrorMessage
|
| def f3()(i: Int)(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:17:6 ----------------------------------------------------------------------
17 | f3()(2) // error
| ^^^^^^^
| missing argument list for method f3 in object ConfusingErrorMessage
|
| def f3()(i: Int)(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:19:2 ----------------------------------------------------------------------
19 | i3 // error
| ^^
| missing argument list for method i3 in object ConfusingErrorMessage
|
| def i3()(using d: DummyImplicit)(): Unit
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/i17123.scala:20:2 ----------------------------------------------------------------------
20 | i3() // error
| ^^^^
| missing argument list for method i3 in object ConfusingErrorMessage
|
| def i3()(using d: DummyImplicit)(): Unit
|
| longer explanation available when compiling with `-explain`
22 changes: 22 additions & 0 deletions tests/neg/i17123.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
object ConfusingErrorMessage {
def m1() = ()
def m2()() = ()
def m3()()() = ()
def f3()(i: Int)() = ()
def i3()(using d: DummyImplicit)() = ()
m1 // error
m1()
m2 // error
m2() // error
m3 // error
m3() // error
m3()() // error
m3()()()
f3 // error
f3() // error
f3()(2) // error
f3()(2)()
i3 // error
i3() // error
i3()()
}
2 changes: 1 addition & 1 deletion tests/neg/i7816.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
object A {
def f()(>) = ??? // error
import f.NonExistent // error
import f.NonExistent
}
28 changes: 22 additions & 6 deletions tests/neg/indent-colons.check
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,31 @@
| Not found: file
|
| longer explanation available when compiling with `-explain`
-- Error: tests/neg/indent-colons.scala:5:2 ----------------------------------------------------------------------------
-- [E178] Type Error: tests/neg/indent-colons.scala:5:2 ----------------------------------------------------------------
5 | tryEither: // error
| ^^^^^^^^^
| missing arguments for method tryEither
-- Error: tests/neg/indent-colons.scala:11:2 ---------------------------------------------------------------------------
| missing argument list for method tryEither
|
| def tryEither[T](x: T)(y: Int => T): T
|
| where: T is a type variable
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/indent-colons.scala:11:2 ---------------------------------------------------------------
11 | tryEither: // error
| ^^^^^^^^^
| missing arguments for method tryEither
-- Error: tests/neg/indent-colons.scala:18:2 ---------------------------------------------------------------------------
| missing argument list for method tryEither
|
| def tryEither[T](x: T)(y: Int => T): T
|
| where: T is a type variable
|
| longer explanation available when compiling with `-explain`
-- [E178] Type Error: tests/neg/indent-colons.scala:18:2 ---------------------------------------------------------------
18 | Some(3).fold: // error
| ^^^^^^^^^^^^
| missing arguments for method fold in class Option
| missing argument list for method fold in class Option
|
| final def fold[B](ifEmpty: => B)(f: A => B): B
|
| longer explanation available when compiling with `-explain`