Skip to content
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

strange error for missing using keyword in implicit argument #19680

Closed
Dieken opened this issue Feb 13, 2024 · 7 comments · Fixed by #20023
Closed

strange error for missing using keyword in implicit argument #19680

Dieken opened this issue Feb 13, 2024 · 7 comments · Fixed by #20023
Assignees
Labels
area:implicits related to implicits area:reporting Error reporting including formatting, implicit suggestions, etc better-errors Issues concerned with improving confusing/unhelpful diagnostic messages itype:enhancement
Milestone

Comments

@Dieken
Copy link

Dieken commented Feb 13, 2024

Compiler version

3.3.1 and 3.4.0-RC4.

Minimized example

@main
def main(args: String*): Unit =
  println("hello")
  val config = Config(8080, "docs.scala-lang.org")
  given Config = config
  println(renderWebsite("/home")(config))

case class Config(port: Int, baseUrl: String)

def renderWebsite(path: String)(using config: Config): String =
  "<html>" + renderWidget(List("cart")) + "</html>"

def renderWidget(items: List[String])(using config: Config): String =
  "<div>" + items.mkString(
    ", "
  ) + s" ${config.port} ${config.baseUrl}" + "</div>"

Output Error/Warning message

-- [E007] Type Mismatch Error: /private/tmp/a.scala:6:33 -----------------------
6 |  println(renderWebsite("/home")(config))
  |                                 ^^^^^^
  |                                 Found:    (config : Config)
  |                                 Required: Int
  |
  | longer explanation available when compiling with `-explain`
1 error found
Errors encountered during compilation

Why this Error/Warning was not helpful

Obviously the error message is wrong.

Suggested improvement

It should remind me removing the whole argument or adding keyword using in line 6.

@Dieken Dieken added area:reporting Error reporting including formatting, implicit suggestions, etc better-errors Issues concerned with improving confusing/unhelpful diagnostic messages itype:enhancement stat:needs triage Every issue needs to have an "area" and "itype" label labels Feb 13, 2024
@Gedochao Gedochao added area:implicits related to implicits and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Feb 13, 2024
@som-snytt
Copy link
Contributor

The message is not wrong, but it would be nice to use the Did you mean...? idiom to add that there was an implicit arg (in last position) in the application of the same type.

Did you mean `using config`? The application already includes a given Config.

It would also be nice for the more usual failure case where there is no given in scope.

Did you mean `using config`? The application requires a given Config.

Migrating a code base from implicit is likely to encounter this mistake.

@odersky
Copy link
Contributor

odersky commented Feb 14, 2024

I think this is a very special case, and one that would likely detract from the true source of errors in 99.9% of the cases. So I am against making a special "did you mean" for this.

On the other hand, even without the implicit parameter complication, the error message is a bit baffling:

                                Found:    (config : Config)
                                Required: Int

Where does the Int come from? I think we should try to explain that it is the apply method of the result type of renderWebSite. Something like:

                                Found:    (config : Config)
                                Required: Int

                                The required type comes from a parameter of the automatically inserted `apply` method of `String`,
                                which is the result type of `renderWebSite`

Or alternatively, show the full expanded call (but this might become very large sometimes).

@mbovel mbovel self-assigned this Feb 14, 2024
@mbovel mbovel added the Spree Suitable for a future Spree label Feb 14, 2024
@som-snytt
Copy link
Contributor

The challenge is to report something in brief (and not under -explain).

Maybe just for the case of "arg of correct type for some parameter in the expression (but perhaps lacks using)" then give the OP the suggested improvement (in some form, perhaps just the expansion).

The required type is just misdirection. (Reminiscent of errors from the days of postfixOps, a puzzler.)

I don't know if OP is in 0.1% of users.

@mbovel
Copy link
Member

mbovel commented Mar 7, 2024

Further minimized:

class Config()
def renderWebsite(path: String)(using config: Config): String = ???
def renderWidget(using Config): Unit = renderWebsite("/tmp")(Config())
-- [E007] Type Mismatch Error: tests/pos/19680.scala:3:67 ----------------------
3 |def renderWidget(using Config): Unit = renderWebsite("/tmp")(Config())
  |                                                             ^^^^^^^^
  |                                                          Found:    Config
  |                                                          Required: Int
  |
  | longer explanation available when compiling with `-explain`

Note that if there is no Config given in scope, then we have an error message about the missing implicit:

class Config()
def renderWebsite(path: String)(using config: Config): String = ???
def renderWidget2: Unit = renderWebsite("/tmp")(Config())
-- [E172] Type Error: tests/pos/19680.scala:3:47 -------------------------------
3 |def renderWidget2: Unit = renderWebsite("/tmp")(Config())
  |                                               ^
  |No given instance of type Config was found for parameter config of method renderWebsite

And here is the error stack trace, for the first case, with the Config given:

        at dotty.tools.dotc.report$.error(report.scala:70)
        at dotty.tools.dotc.typer.ErrorReporting$.errorType(ErrorReporting.scala:32)
        at dotty.tools.dotc.typer.ErrorReporting$.errorTree(ErrorReporting.scala:23)
        at dotty.tools.dotc.typer.ErrorReporting$.errorTree(ErrorReporting.scala:26)
        at dotty.tools.dotc.typer.ErrorReporting$Errors.typeMismatch(ErrorReporting.scala:197)
        at dotty.tools.dotc.typer.Typer.recover$1(Typer.scala:4246)
        at dotty.tools.dotc.typer.Typer.adaptToSubType$1(Typer.scala:4270)
        at dotty.tools.dotc.typer.Typer.adaptNoArgsOther$1(Typer.scala:4079)
        at dotty.tools.dotc.typer.Typer.adaptNoArgs$1(Typer.scala:4159)
        at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:4386)
        at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:3682)
        at dotty.tools.dotc.typer.ProtoTypes$FunProto.typedArg(ProtoTypes.scala:513)
        at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:913)
        at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:913)
        at dotty.tools.dotc.typer.Applications$Application.addTyped$1(Applications.scala:605)
        at dotty.tools.dotc.typer.Applications$Application.matchArgs(Applications.scala:669)
        at dotty.tools.dotc.typer.Applications$Application.init(Applications.scala:491)
        at dotty.tools.dotc.typer.Applications$TypedApply.<init>(Applications.scala:795)
        at dotty.tools.dotc.typer.Applications$ApplyToUntyped.<init>(Applications.scala:912)
        at dotty.tools.dotc.typer.Applications.ApplyTo(Applications.scala:1142)
        at dotty.tools.dotc.typer.Applications.ApplyTo$(Applications.scala:351)
        at dotty.tools.dotc.typer.Typer.ApplyTo(Typer.scala:120)
        at dotty.tools.dotc.typer.Applications.simpleApply$1(Applications.scala:985)
        at dotty.tools.dotc.typer.Applications.realApply$1$$anonfun$2(Applications.scala:1068)
        at dotty.tools.dotc.typer.Typer.tryEither(Typer.scala:3418)
        at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:1079)
        at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:1117)
        at dotty.tools.dotc.typer.Applications.typedApply$(Applications.scala:351)
        at dotty.tools.dotc.typer.Typer.typedApply(Typer.scala:120)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3118)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3202)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3279)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3283)
        at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3394)
        at dotty.tools.dotc.typer.Typer.$anonfun$62(Typer.scala:2608)
        at dotty.tools.dotc.inlines.PrepareInlineable$.dropInlineIfError(PrepareInlineable.scala:256)
        at dotty.tools.dotc.typer.Typer.typedDefDef(Typer.scala:2608)
        at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3100)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3201)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3279)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3283)
        at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3305)
        at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3351)
        at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:2795)
        at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:3106)
        at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3110)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3201)
        ...

@mbovel
Copy link
Member

mbovel commented Mar 15, 2024

This issue was picked for the Issue Spree of March 19th, 2024. @mbovel, @iusildra, @jan-pieter will be working on it. If you have any insight into the issue or guidance on how to fix it, please leave it here.

@mbovel
Copy link
Member

mbovel commented Mar 19, 2024

It's not clear to me how the info about the expected type should flow from FunProto.typedArg to the point where we throw the message, as it seems we don't have this info starting from Typer.adapt.

@mbovel
Copy link
Member

mbovel commented Apr 29, 2024

The challenge is to report something in brief (and not under -explain).

My PR unfortunately currently only adds the message under -explain because I am afraid it could show it too many cases otherwise. I hope this can still be useful.

odersky added a commit that referenced this issue May 1, 2024
@Kordyjan Kordyjan added this to the 3.5.0 milestone May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:implicits related to implicits area:reporting Error reporting including formatting, implicit suggestions, etc better-errors Issues concerned with improving confusing/unhelpful diagnostic messages itype:enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants