-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
go/parser: (*ast.File).Decls is empty after bailout #70725
Comments
Related Issues (Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
Also same thing happens with all these fields: Lines 2902 to 2911 in c8fb6ae
|
Change https://go.dev/cl/634537 mentions this issue: |
The documentation for The core of the problem is that (all?) parse functions collect the ASTs of their respective sub-ASTs in local variables, and then produce the top-level AST node at the end. If a bailout happens, all the intermediate work is lost. In case of the Perhaps we should allocate the top-level nodes first and populate them as we go along (that's what the syntax package does), and use their name as a result parameter. That would address this (and possibly other cases). cc @findleyr for input |
I have always understood the default behavior to mean "abort parsing at the first error", in which case File.Decls must obviously be incomplete. By contrast, AllErrors means keep going until the end of the file, at which point File.Decls will have one entry per import and package-level func/var/const/type. I would be happy to document this behavior, but I don't yet see any reason to change it. |
Not so obviously, actually it is the 10th error that causes a bailout, also the errors might not be in the first declaration, but in the second, in that case i would expect to have the first decl returned. It's hard for me to find a case where this would matter in practice — why someone would try to process a
That is fine, but also looking at the current docs, nothing really mentions that
Oh, this approach sound nice (but not sure whether the complexity is worth it), it might also fix: #70731 |
Quite right; I misspoke, but my point was that it will give up.
For many clients (e.g. a compiler), there are only two interesting outcomes: complete success, or failure with informative (but not overwhelming) error messages. For such clients, the default behavior makes sense.
FWIW, those two modes are for quickly extracting project structure information from a file while doing the least amount of parsing work.
Yes, many of our doc comments are a little too brief. The temptation to keep inline comments short enough to stop them from wrapping the line can be a disincentive to recording things that really ought to be recorded. |
Right, right, but it those cases (i assume) we don't process further the |
I agree, that does seem like an odd thing to do. |
Returning 10 errors seems very much like overfitting to an old command-line use case (probably gofmt). I agree with @adonovan, and think the fix here is documentation: if you care about the resulting tree in the presence of errors, you should be using AllErrors. Doing more work when AllErrors is not set seems like a regression: presumably it is better for most callers to fail fast (as is currently done).
I don't think we should do this. There are already fewer invariants for invalid parse trees, which can be a challenge when developing tools. If we return "whatever was set" when we bail out, then even those invariants go out the window. |
FWIW: The Go compiler reports 10 errors and then stops. Hence the 10. |
Currently when
parser.ParseFile
is executed withoutparser.AllErrors
the parsing is stopped, but the(*ast.File).Decls
field is not populated with the parsed (valid and invalid) declarations:Reproducer:
I think that we should return at least a partial AST in this case, or we should document this behavior.
CC @adonovan @griesemer
The text was updated successfully, but these errors were encountered: