@@ -35,6 +35,7 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError
35
35
use rustc_session:: parse:: ParseSess ;
36
36
use rustc_span:: source_map:: { Span , DUMMY_SP } ;
37
37
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
38
+ use rustc_span:: MultiSpan ;
38
39
use tracing:: debug;
39
40
40
41
use std:: ops:: Range ;
@@ -145,7 +146,11 @@ pub struct Parser<'a> {
145
146
146
147
/// This allows us to recover when the user forget to add braces around
147
148
/// multiple statements in the closure body.
148
- pub last_closure_body : Option < Span /* The closing `|` of the closure declarator. */ > ,
149
+ pub last_closure_body : Option < (
150
+ Span , /* The whole body. */
151
+ Span , /* The closing `|` of the closure declarator. */
152
+ Span , /* What we parsed as closure body. */
153
+ ) > ,
149
154
}
150
155
151
156
/// Indicates a range of tokens that should be replaced by
@@ -779,15 +784,19 @@ impl<'a> Parser<'a> {
779
784
let token_str = pprust:: token_kind_to_string ( t) ;
780
785
781
786
match self . last_closure_body . take ( ) {
782
- Some ( right_pipe_span) if self . token . kind == TokenKind :: Semi => {
787
+ Some ( ( closure_span, right_pipe_span, expr_span) )
788
+ if self . token . kind == TokenKind :: Semi =>
789
+ {
783
790
// Finding a semicolon instead of a comma
784
791
// after a closure body indicates that the
785
792
// closure body may be a block but the user
786
793
// forgot to put braces around its
787
794
// statements.
788
795
789
796
self . recover_missing_braces_around_closure_body (
797
+ closure_span,
790
798
right_pipe_span,
799
+ expr_span,
791
800
expect_err,
792
801
) ?;
793
802
@@ -868,16 +877,13 @@ impl<'a> Parser<'a> {
868
877
869
878
fn recover_missing_braces_around_closure_body (
870
879
& mut self ,
880
+ closure_span : Span ,
871
881
right_pipe_span : Span ,
882
+ expr_span : Span ,
872
883
mut expect_err : DiagnosticBuilder < ' _ > ,
873
884
) -> PResult < ' a , ( ) > {
874
885
let initial_semicolon = self . token . span ;
875
886
876
- expect_err. span_help (
877
- initial_semicolon,
878
- "This `;` turns the expression into a statement, which must be placed in a block" ,
879
- ) ;
880
-
881
887
while self . eat ( & TokenKind :: Semi ) {
882
888
let _ = self . parse_stmt ( ForceCollect :: Yes ) ?;
883
889
}
@@ -889,6 +895,25 @@ impl<'a> Parser<'a> {
889
895
let preceding_pipe_span = right_pipe_span;
890
896
let following_token_span = self . token . span ;
891
897
898
+ let mut first_note = MultiSpan :: from ( vec ! [ initial_semicolon] ) ;
899
+ first_note. push_span_label (
900
+ initial_semicolon,
901
+ "this `;` turns the preceding expression into a statement" . to_string ( ) ,
902
+ ) ;
903
+ first_note. push_span_label (
904
+ expr_span,
905
+ "this expression is a statement because of the trailing semicolon" . to_string ( ) ,
906
+ ) ;
907
+ expect_err. span_note ( first_note, "statement found outside of a block" ) ;
908
+
909
+ let mut second_note = MultiSpan :: from ( vec ! [ closure_span] ) ;
910
+ second_note. push_span_label ( closure_span, "this is the parsed closure..." . to_string ( ) ) ;
911
+ second_note. push_span_label (
912
+ following_token_span,
913
+ "...but likely you meant the closure to end here" . to_string ( ) ,
914
+ ) ;
915
+ expect_err. span_note ( second_note, "the closure body may be incorrectly delimited" ) ;
916
+
892
917
expect_err. set_span ( vec ! [ preceding_pipe_span, following_token_span] ) ;
893
918
894
919
let opening_suggestion_str = " {" . to_string ( ) ;
0 commit comments