diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 2f28975dd066..e0e43169820a 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -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 diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index f504a4034631..36dc8a642afc 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -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. diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index 65ebeb02c667..1fe38ce5e801 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -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 diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 9875c508c9fd..fba08fd84d0c 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -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, diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 32b5fde689ec..126d109889e1 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -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]: diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index a575238f7cd4..1949304ca287 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -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 = diff --git a/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala b/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala index 2f35ccb35434..2e4b7bf1bb3f 100644 --- a/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala +++ b/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala @@ -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, ") = ??? // error - import f.NonExistent // error + import f.NonExistent } \ No newline at end of file diff --git a/tests/neg/indent-colons.check b/tests/neg/indent-colons.check index 102d41592014..f77d491f8b8f 100644 --- a/tests/neg/indent-colons.check +++ b/tests/neg/indent-colons.check @@ -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`