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

Confusing 'invalid indentation' errors reported when indentation is not at fault #15667

Open
jrfondren opened this issue Oct 21, 2020 · 9 comments

Comments

@jrfondren
Copy link
Contributor

Compilation can fail with "Error: invalid indentation" given code that visibly lacks any indentation problems.

should be: expression expected, but found ...

var n: int
if true:
  n++
echo n  # invalid indentation

vs. the more useful message from this complete program:

1 +   # expression expected, but found '[EOF]'

should be: expression has no type (or is ambiguous)

proc ex(n: int, m: int = 0) = echo n
ex(n=1, 1)
ex n=1, 1  # bad indentation

vs. the still confusing

proc ex(n: int, m: int = 0) = echo n
ex(n=1)
ex n=1  # undeclared identifier: 'n'

vs.

proc ex(n: int, m: int = 0) = echo n
var n: int
ex(n=1)
ex n=1  # expression 'ex n, 0' has no type (or is ambiguous)

should be: expression ... has no type (or is ambiguous)

var a, b: int
a = b = 10  # invalid indentation

vs.

var a, b: int
a = (b = 10)  # expression 'b = 10' has no type (or is ambiguous)

should be: type mismatch

var (k, v) = 1, 2  # invalid indentation

vs.

proc ex: auto =
  return 1, 2  # invalid indentation
var (k, v) = ex()

vs.

proc ex: (int, int) =
  return 1, 2  # type mismatch: got <int literal(1)> but expected '(int, int)'
var (k, v) = ex()

Additional Information

I've run into this personally, and just fixed the error and moved on, but it's still confusing to have to look and wonder if indentation is really invalid or not.
I imagine it's come up a lot in IRC; here's the latest occurrence: https://irclogs.nim-lang.org/21-10-2020.html#08:44:57

when writing the ++ I was thinking it might not be that in nim, but I got distracted by the error message so forgot about it, lol

The last example is a variation of issue #11020
It's mentioned in #14952 that this error is

Nim's favorite obscure fallback error message.

Possible mitigation

When nim fails to compile with an error that is merely "invalid indentation", it could link to a nim-lang.org page showing the other ways that this error might be triggered, or it could copy rustc a bit and add an additional message like

Don't think the indentation is the problem? Run: nim --explain invalidindent

and that command can dump other ways to trigger this error into a pager.

$ nim -v
Nim Compiler Version 1.4.0 [Linux: amd64]
Compiled at 2020-10-16
Copyright (c) 2006-2020 by Andreas Rumpf

git hash: bdcd87afca238a0a7b2c70971827cf9172817b12
active boot switches: -d:release
@timotheecour
Copy link
Member

timotheecour commented Oct 22, 2020

maybe add an example from #10229 which is a common pitfall (in particular #10229 (comment)), which was closed as wontfix due to noone having stepped up to work on it

@jrfondren
Copy link
Contributor Author

One that I almost reported separately is

type
  Odd = ref object
    id: int

proc `=copy`(dest: var Odd; source: Odd) {.error.}

Which yields

Error: signature for '=copy' must be proc[T: object](x: var T; y: T)

What I didn't notice until I was writing up the issue is that the T: object is the important information there: the code is providing a ref object instead. So rather than change the text of the error, I think this would be another good candidate for an --explain feature.

I'll give this feature a try.

@timotheecour
Copy link
Member

and yet another bug report that was just filed that's the same as this: #16232

I'm bumping this up to medium priority since it seems to trip so many people (and would generally improve user experience for everyone)

@NebulaFox
Copy link

NebulaFox commented Dec 3, 2020

Since my issue is a duplicate of this one, I'll write my findings here

@timotheecour I kind of got curious, and started looking into the parser code to debug it for my cases. I narrowed it down to the optPar(). In my case, it is in parserPar(). The messesage comes about because the parser has moved on to the next token, EOF, causing the indentation level to reset. optPar is correctly looking for a something with a higher or equal to indentation, but the condition is not met.

Looking into the grammer, I believe optPar – optional paragraphs? – is used through out to handle when syntax is split across lines.

If this was useful, I am happy to look into the other cases and sees what's going on.

@timotheecour
Copy link
Member

@NebulaFox please make a PR since you've started looking at this; I'd recommend focusing on improving at least just 1 common case for a start.
for example:

proc fn() {.exportc.}
  echo 1
Error: invalid indentation

=> instead:

Error: invalid indentation or missing `=` at main.nim(1,22)

@NebulaFox
Copy link

@timotheecour I have not done any code changes yet, just debugging at the moment.

Looking at the case that you have provided, I think error message invalid indentation is wrong for a different reason. It occurs in indAndComment under parseRoutine. Through trial and error, I have concluded that indAndComment is parsing for doc comments. Looking at the grammer, since doc comments are optional, I do not currently understand why incAndComment is emitting an error.

I could create a PR with removal of the emitting error in indAndComment to get the ball rolling?

Removing the emitting error from incAndComment we end up in another invalid indentation error but this time it is correct. It occurs in parseTopLevelStmt. From the grammar, the equals, =, that is used to define the implementation is optional. So the example is parsed as a definition of fn() and a top level echo statement that is incorrectly indented. The message of the error could be changed to be more clearer, top level statement is incorrectly indented.

proc fn() {.exportc.}
  echo 1

Ideally we want the parser to mention a missing equals when it detects something that looks like an implementation on a procedure. The parser only has history as far back as the context it is in. The context of parseTopLevelStmt would not allow us to say there is possibily of a missing equals.

As far as I can see, the parser is behaving correctly, but lacks anyway to infer user intent. I propose that we add a layer, to or above, the parser, that can then keep track of things to infer user intent to give better error messages. We can then use the above cases to test the compiler against and determine the correct error message. I am not fully aware if the test suit is capable of handling such integration test/blackboxing testing.

Thoughts?

timotheecour added a commit to timotheecour/Nim that referenced this issue Dec 4, 2020
timotheecour added a commit to timotheecour/Nim that referenced this issue Dec 4, 2020
timotheecour added a commit to timotheecour/Nim that referenced this issue Dec 4, 2020
@timotheecour
Copy link
Member

timotheecour commented Dec 4, 2020

I have a candidate PR: timotheecour#418 that fixes 1 of the most common issues:

I am not fully aware if the test suit is capable of handling such integration test/blackboxing testing.

the test suite (tests/) can do anything, including calling the compiler directly and verifying the error message you get is as expected

@m33m33
Copy link

m33m33 commented Apr 9, 2021

An unneeded closing parenthesis triggers the Error: invalid indentationmessage.

I guess something like Error: Unmatched parenthesis would be better in this case:

try:
  a = client.getContent(arg1 & arg2.getStr)
except:
  echo "Error when requesting network API:" , arg2.getStr)     =====> Error: invalid indentation
  continue

timotheecour added a commit to timotheecour/Nim that referenced this issue Apr 9, 2021
Araq pushed a commit that referenced this issue Apr 10, 2021
…=` could be missing (#16397)

* refs #15667 improve invalid indentation errors

* also show line info where = is missing

* add test

* add more tests
@timotheecour
Copy link
Member

#16397 was merged; see future work mentioned in that PR

sthagen added a commit to sthagen/nim-lang-Nim that referenced this issue Apr 10, 2021
refs nim-lang#15667 improve invalid indentation errors, report when & where `…
PMunch pushed a commit to PMunch/Nim that referenced this issue Mar 28, 2022
… where `=` could be missing (nim-lang#16397)

* refs nim-lang#15667 improve invalid indentation errors

* also show line info where = is missing

* add test

* add more tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants