Skip to content

Distinguish delim kind to decide whether to emit unexpected closing delimiter #138554

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

xizheyin
Copy link
Contributor

@xizheyin xizheyin commented Mar 16, 2025

Fixes #138401

@rustbot
Copy link
Collaborator

rustbot commented Mar 16, 2025

r? @compiler-errors

rustbot has assigned @compiler-errors.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 16, 2025
@compiler-errors
Copy link
Member

r? compiler

@rustbot rustbot assigned estebank and unassigned compiler-errors Mar 21, 2025
@chenyukang
Copy link
Member

I changed this part last year, will review this PR later.

r? @chenyukang

@rustbot rustbot assigned chenyukang and unassigned estebank Apr 7, 2025
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 11, 2025
@chenyukang
Copy link
Member

I think this solution introduces some kind of regression on other scenarios(such as the cases I commented).

Maybe we should consider this as a special corner case and provide a special diagnostic for it, it is the pattern that one delimiter is missing the openning delimiter(it's in the inner part), except for this everything is ok, so we should suggest something like "missing openning delimiter ....".

such as:

{ ... {. ) ... }...} missing a inner (
{ ... [ ], ] ...} missing a inner [

@chenyukang
Copy link
Member

@rustbot author

@rustbot
Copy link
Collaborator

rustbot commented Apr 11, 2025

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@xizheyin
Copy link
Contributor Author

Thanks, I will revise it soon!

@xizheyin xizheyin changed the title [Lexer] Remove spurious unexpected delimiter error by matching remain… Distinguish delim kind to decide whether to emit unexpected closing delimiter Apr 12, 2025
@xizheyin
Copy link
Contributor Author

This seems like quite a lot of changes, I'll comment in the code to make it easier to REVIEW.

In the first commit, I added the test.

In the second commit I did some clean. I changed a variable name, the original name was inaccurate, I used open_delimiters instead of open_braces for identifying blocks, one should compare spans, not just brace'{'.

In the third commit, I make a distinction between the different delimiters before triggering a unexpected closing delimiter error. But I found that missing open delim note is what triggers in unexpected closing delimiter error.
Therefore, to emit missing open delim note, I also moved missing open delim note to
mismatched closing delimiter error, which can be emitted without delaying to
unexpected closing delimiter error.
And I moved function make_unclosed_delims_error
to src/lexer/diagnostics.rs for clean. And some other clean.

@xizheyin xizheyin requested a review from chenyukang April 12, 2025 11:02
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 12, 2025
@xizheyin
Copy link
Contributor Author

I've combined them into one line so it's more aesthetically pleasing.

mismatched closing delimiter, may missing open `(`

Since the mismatched closing delimiter note and the unclosed delimiter note are related, it may be the better to keep it.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@@ -2,7 +2,7 @@ error: mismatched closing delimiter: `]`
--> <crate attribute>:1:4
|
LL | #![(]
| -^^ mismatched closing delimiter
| -^^ mismatched closing delimiter, may missing open `[`
| ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems we are suggestting writing code like this?

#![([]

seems not helpful.

@@ -2,7 +2,7 @@ error: mismatched closing delimiter: `)`
--> $DIR/issue-102878.rs:1:35
|
LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
| -^ ^ mismatched closing delimiter
| -^ ^ mismatched closing delimiter, may missing open `(`
| ||
Copy link
Member

@chenyukang chenyukang Apr 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is worse too, we are not sure we should replace the left { to ( or replace the right ) to }.

so, the better way is do not suggest any direction.

I think we should only suggest missing a open(or closing) delimiter in the scenario that if we added a open(or closing) delimiter, there will be no error.

@@ -4,16 +4,7 @@ error: mismatched closing delimiter: `]`
LL | if 1 < 2 {
| ^ unclosed delimiter
LL | let _a = vec!];
| ^ mismatched closing delimiter
| ^ mismatched closing delimiter, may missing open `[`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for example, this is the scenario we should report missing open [, because except for this ] is lefted unmistached, all the other outer delimiter are matched correctly.

@@ -2,7 +2,7 @@ error: mismatched closing delimiter: `)`
--> $DIR/do-not-suggest-semicolon-before-array.rs:5:5
|
LL | [1, 3)
| ^ ^ mismatched closing delimiter
| ^ ^ mismatched closing delimiter, may missing open `(`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is similar, it maybe:

[1, 3] or (1, 3), we can not determine which is right at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example should be similar to Result. In fact, it is difficult for a compiler to determine which one is correct. Do you have any suggestions for implementation? :)

@@ -4,16 +4,7 @@ error: mismatched closing delimiter: `)`
LL | async fn obstest() -> Result<> {
| ^ unclosed delimiter
LL | let obs_connect = || -> Result<(), MyError) {
| ^ mismatched closing delimiter
| ^ mismatched closing delimiter, may missing open `(`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this suggesting:

Result((), MyError)

while right code should:

Result<(), MyError>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, for this example, how do we know whether it should be) or > through the oracle? It seems easy for humans to understand, but it is not easy in the compiler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, compiler can not suggest anything for this, so we should not add the new label "may missing open (". just keep the current ^ mismatched closing delimiter is ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, that is to say, the compiler should only give advice when it is sure, otherwise it just needs to report an error.

@xizheyin
Copy link
Contributor Author

I don't have a good way to judge whether adding the open delimiter is a better way. As in the previous implementation, there will always be some false positives.

If we have to make a balance, should we make suggestions as comprehensively as possible, or would we rather not make suggestions and minimize false positives?

Maybe I need to refactor this code more.

LL | pub fn foo(x: i64) -> i64 {
| ^ unclosed delimiter
LL | x.abs)
| ^ mismatched closing delimiter, may missing open `(`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to suggest like this:

missing open `(` for this delimiter

as the origin issue reported wrote in #138401

@@ -23,7 +24,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
// Invisible delimiters cannot occur here because `TokenTreesReader` parses
// code directly from strings, with no macro expansion involved.
debug_assert!(!matches!(delim, Delimiter::Invisible(_)));
buf.push(match self.lex_token_tree_open_delim(delim) {
buf.push(match self.lex_token_tree_open_delim(delim, self.token.span) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this may have a performance effect since it's on the normal code path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, after the modification is confirmed, perhaps a time robot can be used to test it.

@chenyukang
Copy link
Member

I have a look at the current code, current output is:

error: mismatched closing delimiter: `)`
 --> ...\test.rs:1:27
  |
1 | pub fn foo(x: i64) -> i64 {
  |                           ^ unclosed delimiter
2 |     x.abs)
  |          ^ mismatched closing delimiter

error: unexpected closing delimiter: `}`
 --> ...\test.rs:3:1
  |
2 |     x.abs)
  |          - missing open `(` for this delimiter
3 | }
  | ^ unexpected closing delimiter

error: aborting due to 2 previous errors

The first diagnostic message is reported at here(you moved it into lexer, it is ok):
https://github.com/chenyukang/rust/blob/c8f94230282a8e8c1148f3e657f0199aad909228/compiler/rustc_parse/src/parser/mod.rs#L1766-L1785

The second diagnostic is reported at here:
https://github.com/chenyukang/rust/blob/c8f94230282a8e8c1148f3e657f0199aad909228/compiler/rustc_parse/src/lexer/diagnostics.rs#L61

To resolve the issue in #138401, can we just remove the first diagnostic if we could report the second one? or at least reorder these two diagnostics, which could also reduce the confusion.

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
…when push matching_block_span

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
…elimiter

To emit missing open delim note, I also moved `missing open delim` note to
`mismatched closing delimiter` error, which can emit without delaying to
`unexpected closing delimiter` error. And I moved `make_unclosed_delims_error`
to src/lexer/diagnostics.rs for clean. And some other clean.

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
@xizheyin
Copy link
Contributor Author

xizheyin commented Apr 22, 2025

This part of the code conflicted with master, so I submitted the PR #140147 first to do some cleanup, otherwise the code for this PR would have been rather messy. @chenyukang

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Better handling of missing closing or opening delimiters, well distinct by type of delimiter
6 participants