-
Notifications
You must be signed in to change notification settings - Fork 888
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
update handling of parser errors #3920
Conversation
@@ -76,3 +76,7 @@ version = "610.0.0" | |||
package = "rustc-ap-syntax_pos" | |||
version = "610.0.0" | |||
|
|||
[dependencies.rustc_data_structures] | |||
package = "rustc-ap-rustc_data_structures" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was already a part of the dependency tree (since nearly every rustc-ap-*
package uses it), but adding it directly to gain access to one of the traits for use in the parser emitter.
src/syntux/session.rs
Outdated
Box::new(SilentEmitter {}) | ||
} | ||
|
||
/// Emit errors against every files expect ones specified in the `ignore_path_set`. | ||
struct SilentOnIgnoredFilesEmitter { | ||
ignore_path_set: Rc<IgnorePathSet>, | ||
source_map: Rc<SourceMap>, | ||
emitter: EmitterWriter, | ||
emitter: Box<dyn Emitter + sync::Send>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change also makes it a lot easer to unit test the emitter logic vs explicitly using the EmitterWriter
struct
10892f4
to
972a2a7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the PR! However, I quite do not understand the motivation behind this PR. We should not surface any parsing errors from ignored files as they tend to contain malformed syntax.
the parser won't be able to give rustfmt the ast anyway in the event of a fatal error
rustfmt doesn't parse the ignored files, so this shouldn't be a problem.
This is basically some fixes/follow ups to the change from #3782 where we added support to not have rustfmt exit with an error when it encounters recoverable parser errors that originate from ignored files. There was also some relevant conversation around that original change in #3779 and #3777 for historical context. There's two core fixes in this PR: incorrect handling of parser errors when
|
@calebcartwright Thank you for the explanation! It helped me understand the intention of this PR and the actual problem 😃 Now that I think about it, it seems that the root cause of the problem is how we parse files and create mappings between filenames and AST nodes. In the current implementation, first, in This approach has two problems:
To fix the actual cause of the problem, we need to create a mapping from file names to the AST node without creating a complete AST. I think that this is possible by rolling out our module resolver. I am thinking of something like the following: // This stack keeps track of items inside a file.
let mut item_stack = vec![];
// Initialize the stack with the items in the entry file.
for item in main_file.sub_mods() {
item_stack.push((item, main_file.file_name()));
}
// This is the mapping from filename to AST node.
let mut file_to_ast_node_map = BTreeMap::new();
while let mut Some((item, file_name)) = item_stack.pop() {
if !item.is_mod() {
continue;
}
// If the mod should be ignored, we won't parse it.
if should_ignore(item) {
continue;
}
// Try to parse the mod item. If succeed then we add a mapping.
// Otherwise, we return an error or keep processing, depending on
// the configuration.
match parse_mod_item(item) {
Ok(parsed) => souremap.insert(file_name, parsed),
Err(err) => {
if error_on_unparsable_file() {
return Err(err);
} else {
continue;
}
}
}
}
}
Ok(file_to_ast_node_map) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concerning this PR, this looks good to me as it fixes the bug and improves the user's experience. However, as I mentioned in the above comment, please note that we may need to reconsider how we parse the module tree, and hence, we may replace the relevant code entirely with the new approach.
@calebcartwright Again, thank you for your PR and explanation, it helped me a lot.
That makes a lot of sense to me @topecongiro. I presume we'd also need to always set Otherwise, IIUC, the parser would still continue go through and construct the entire AST up front |
Yes! |
If you'd like, I'll open a new issue to track the work of updating the parser flow per your above solution. Though I expect I may get stuck along the way, I could look into trying to implement it as well. My thinking is that it feels like it would be good to have this new parser solution in place before fully switching from |
That helps a lot, thanks!
❤️ You should probably utilize
My understanding is that switching from |
No, no concerns there. I was just thinking it'd be nice to avoid flipping the bool in a few places like this: Lines 73 to 93 in a35c82b
since the entire check would then need to be removed as part of the new parser solution. Minor stuff like that though, so I'll go ahead and finish up the |
backported in #4100 |
A couple minor updates to the handling of parser errors in order to cover a few additional scenarios. Follow up to #3782 and refs #3916 (comment)
hide_parse_errors
is true), regardless of whether the source file isignore
d because the parser won't be able to give rustfmt the ast anyway in the event of a fatal error. Previously rustfmt was suppressing the fatal parser error text if the source file wasignore
d even though rustfmt wouldn't be able to continue and would have to exit with an error.hide_parse_errors
is true, the same logic checks are applied to see if DB source file origin was in anignore
d file so that the same error reset logic can be used to ignore the recoverable parser errors