gleam-lang / gleam

⭐️ A friendly language for building type-safe, scalable systems!
https://gleam.run
Apache License 2.0
16.7k stars 698 forks source link

Improve error message for function call inside constant #2983

Closed giacomocavalieri closed 2 months ago

giacomocavalieri commented 3 months ago
pub fn thing() {
  "a"
}

const wibble = thing()

This snippet of code results in this error message:

error: Syntax error
  ┌─ /src/main.gleam:7:21
  │
7 │ const wibble = thing()
  │                     ^ I was not expecting this

Expected one of: 
An import, const, type, if block, or function.

I think that's because the compiler sees it as:

const wibble = thing
()

And not as a function call

Another example is when you wrap the function call in a constructor/list/etc:

const thing = [wibble()]
//                   ^ I was not expecting this
pub fn wibble() { todo }
MystPi commented 3 months ago

A bit unrelated, but should we update the Expected one of: message to remove the if block expectation? I noticed it in your example error message.

giacomocavalieri commented 3 months ago

Nice catch! I'll open a separate issue for that

lpil commented 3 months ago

Thanks folks

nino commented 2 months ago

I'd like to make an attempt at solving this! 🤞

lpil commented 2 months ago

Thank you!

nino commented 2 months ago

I've gotten to a point where I'm getting a nice error message for a valid-looking function call:

error: Syntax error
  ┌─ /src/parse/error.gleam:3:18
  │
3 │ const wib: Int = wibble()
  │                  ^^^^^^^^ Functions can only be called within other functions

Now the question I'm trying to figure out is what to show when there's an invalid-looking function call. Right now I have

error: Syntax error
  ┌─ /src/parse/error.gleam:3:25
  │
3 │ const wib: Int = wibble(&)
  │                         ^ I can't figure out what to do with this character

Hint: Is it a typo?

This matches the error message we get with incorrect function calls generally (eg let a = foo(&bar)), but I don't know if it should. We'd first be telling the user that their function-call syntax is wrong, and after they fix it, we'll tell them they can't call functions here anyway.

An alternative might be to assume that everything from ( until a syntax error is an attempt at a function call, and we'd show something like

error: Syntax error
  ┌─ /src/parse/error.gleam:3:18
  │
3 │ const wib: Int = wibble(foo, &bar)
  │                  ^^^^^^^^^^^^^ Functions can only be called within other functions

Any preferences?

lpil commented 2 months ago

Let's leave it as erroring on the first syntax error (in this case the &) as that's what we do everywhere else, and it's not a mistake we've seen people make.