@@ -14,7 +14,7 @@ use crate::ThinVec;
14
14
use crate :: util:: parser:: AssocOp ;
15
15
use errors:: { Applicability , DiagnosticBuilder , DiagnosticId } ;
16
16
use rustc_data_structures:: fx:: FxHashSet ;
17
- use syntax_pos:: { Span , DUMMY_SP , MultiSpan } ;
17
+ use syntax_pos:: { Span , DUMMY_SP , MultiSpan , SpanSnippetError } ;
18
18
use log:: { debug, trace} ;
19
19
use std:: mem;
20
20
@@ -199,6 +199,10 @@ impl<'a> Parser<'a> {
199
199
& self . sess . span_diagnostic
200
200
}
201
201
202
+ crate fn span_to_snippet ( & self , span : Span ) -> Result < String , SpanSnippetError > {
203
+ self . sess . source_map ( ) . span_to_snippet ( span)
204
+ }
205
+
202
206
crate fn expected_ident_found ( & self ) -> DiagnosticBuilder < ' a > {
203
207
let mut err = self . struct_span_err (
204
208
self . token . span ,
@@ -549,8 +553,10 @@ impl<'a> Parser<'a> {
549
553
ExprKind :: Binary ( op, _, _) if op. node . is_comparison ( ) => {
550
554
// respan to include both operators
551
555
let op_span = op. span . to ( self . token . span ) ;
552
- let mut err = self . diagnostic ( ) . struct_span_err ( op_span,
553
- "chained comparison operators require parentheses" ) ;
556
+ let mut err = self . struct_span_err (
557
+ op_span,
558
+ "chained comparison operators require parentheses" ,
559
+ ) ;
554
560
if op. node == BinOpKind :: Lt &&
555
561
* outer_op == AssocOp :: Less || // Include `<` to provide this recommendation
556
562
* outer_op == AssocOp :: Greater // even in a case like the following:
@@ -717,8 +723,6 @@ impl<'a> Parser<'a> {
717
723
path. span = ty_span. to ( self . prev_span ) ;
718
724
719
725
let ty_str = self
720
- . sess
721
- . source_map ( )
722
726
. span_to_snippet ( ty_span)
723
727
. unwrap_or_else ( |_| pprust:: ty_to_string ( & ty) ) ;
724
728
self . diagnostic ( )
@@ -889,7 +893,7 @@ impl<'a> Parser<'a> {
889
893
err. span_label ( await_sp, "while parsing this incorrect await expression" ) ;
890
894
err
891
895
} ) ?;
892
- let expr_str = self . sess . source_map ( ) . span_to_snippet ( expr. span )
896
+ let expr_str = self . span_to_snippet ( expr. span )
893
897
. unwrap_or_else ( |_| pprust:: expr_to_string ( & expr) ) ;
894
898
let suggestion = format ! ( "{}.await{}" , expr_str, if is_question { "?" } else { "" } ) ;
895
899
let sp = lo. to ( expr. span ) ;
@@ -923,6 +927,48 @@ impl<'a> Parser<'a> {
923
927
}
924
928
}
925
929
930
+ /// Recover a situation like `for ( $pat in $expr )`
931
+ /// and suggest writing `for $pat in $expr` instead.
932
+ ///
933
+ /// This should be called before parsing the `$block`.
934
+ crate fn recover_parens_around_for_head (
935
+ & mut self ,
936
+ pat : P < Pat > ,
937
+ expr : & Expr ,
938
+ begin_paren : Option < Span > ,
939
+ ) -> P < Pat > {
940
+ match ( & self . token . kind , begin_paren) {
941
+ ( token:: CloseDelim ( token:: Paren ) , Some ( begin_par_sp) ) => {
942
+ self . bump ( ) ;
943
+
944
+ let pat_str = self
945
+ // Remove the `(` from the span of the pattern:
946
+ . span_to_snippet ( pat. span . trim_start ( begin_par_sp) . unwrap ( ) )
947
+ . unwrap_or_else ( |_| pprust:: pat_to_string ( & pat) ) ;
948
+
949
+ self . struct_span_err ( self . prev_span , "unexpected closing `)`" )
950
+ . span_label ( begin_par_sp, "opening `(`" )
951
+ . span_suggestion (
952
+ begin_par_sp. to ( self . prev_span ) ,
953
+ "remove parenthesis in `for` loop" ,
954
+ format ! ( "{} in {}" , pat_str, pprust:: expr_to_string( & expr) ) ,
955
+ // With e.g. `for (x) in y)` this would replace `(x) in y)`
956
+ // with `x) in y)` which is syntactically invalid.
957
+ // However, this is prevented before we get here.
958
+ Applicability :: MachineApplicable ,
959
+ )
960
+ . emit ( ) ;
961
+
962
+ // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
963
+ pat. and_then ( |pat| match pat. node {
964
+ PatKind :: Paren ( pat) => pat,
965
+ _ => P ( pat) ,
966
+ } )
967
+ }
968
+ _ => pat,
969
+ }
970
+ }
971
+
926
972
crate fn could_ascription_be_path ( & self , node : & ast:: ExprKind ) -> bool {
927
973
self . token . is_ident ( ) &&
928
974
if let ast:: ExprKind :: Path ( ..) = node { true } else { false } &&
@@ -1105,17 +1151,14 @@ impl<'a> Parser<'a> {
1105
1151
crate fn check_for_for_in_in_typo ( & mut self , in_span : Span ) {
1106
1152
if self . eat_keyword ( kw:: In ) {
1107
1153
// a common typo: `for _ in in bar {}`
1108
- let mut err = self . sess . span_diagnostic . struct_span_err (
1109
- self . prev_span ,
1110
- "expected iterable, found keyword `in`" ,
1111
- ) ;
1112
- err. span_suggestion_short (
1113
- in_span. until ( self . prev_span ) ,
1114
- "remove the duplicated `in`" ,
1115
- String :: new ( ) ,
1116
- Applicability :: MachineApplicable ,
1117
- ) ;
1118
- err. emit ( ) ;
1154
+ self . struct_span_err ( self . prev_span , "expected iterable, found keyword `in`" )
1155
+ . span_suggestion_short (
1156
+ in_span. until ( self . prev_span ) ,
1157
+ "remove the duplicated `in`" ,
1158
+ String :: new ( ) ,
1159
+ Applicability :: MachineApplicable ,
1160
+ )
1161
+ . emit ( ) ;
1119
1162
}
1120
1163
}
1121
1164
@@ -1128,12 +1171,12 @@ impl<'a> Parser<'a> {
1128
1171
1129
1172
crate fn eat_incorrect_doc_comment_for_arg_type ( & mut self ) {
1130
1173
if let token:: DocComment ( _) = self . token . kind {
1131
- let mut err = self . diagnostic ( ) . struct_span_err (
1174
+ self . struct_span_err (
1132
1175
self . token . span ,
1133
1176
"documentation comments cannot be applied to a function parameter's type" ,
1134
- ) ;
1135
- err . span_label ( self . token . span , "doc comments are not allowed here" ) ;
1136
- err . emit ( ) ;
1177
+ )
1178
+ . span_label ( self . token . span , "doc comments are not allowed here" )
1179
+ . emit ( ) ;
1137
1180
self . bump ( ) ;
1138
1181
} else if self . token == token:: Pound && self . look_ahead ( 1 , |t| {
1139
1182
* t == token:: OpenDelim ( token:: Bracket )
@@ -1145,12 +1188,12 @@ impl<'a> Parser<'a> {
1145
1188
}
1146
1189
let sp = lo. to ( self . token . span ) ;
1147
1190
self . bump ( ) ;
1148
- let mut err = self . diagnostic ( ) . struct_span_err (
1191
+ self . struct_span_err (
1149
1192
sp,
1150
1193
"attributes cannot be applied to a function parameter's type" ,
1151
- ) ;
1152
- err . span_label ( sp, "attributes are not allowed here" ) ;
1153
- err . emit ( ) ;
1194
+ )
1195
+ . span_label ( sp, "attributes are not allowed here" )
1196
+ . emit ( ) ;
1154
1197
}
1155
1198
}
1156
1199
@@ -1206,18 +1249,19 @@ impl<'a> Parser<'a> {
1206
1249
self . expect ( & token:: Colon ) ?;
1207
1250
let ty = self . parse_ty ( ) ?;
1208
1251
1209
- let mut err = self . diagnostic ( ) . struct_span_err_with_code (
1210
- pat. span ,
1211
- "patterns aren't allowed in methods without bodies" ,
1212
- DiagnosticId :: Error ( "E0642" . into ( ) ) ,
1213
- ) ;
1214
- err. span_suggestion_short (
1215
- pat. span ,
1216
- "give this argument a name or use an underscore to ignore it" ,
1217
- "_" . to_owned ( ) ,
1218
- Applicability :: MachineApplicable ,
1219
- ) ;
1220
- err. emit ( ) ;
1252
+ self . diagnostic ( )
1253
+ . struct_span_err_with_code (
1254
+ pat. span ,
1255
+ "patterns aren't allowed in methods without bodies" ,
1256
+ DiagnosticId :: Error ( "E0642" . into ( ) ) ,
1257
+ )
1258
+ . span_suggestion_short (
1259
+ pat. span ,
1260
+ "give this argument a name or use an underscore to ignore it" ,
1261
+ "_" . to_owned ( ) ,
1262
+ Applicability :: MachineApplicable ,
1263
+ )
1264
+ . emit ( ) ;
1221
1265
1222
1266
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
1223
1267
let pat = P ( Pat {
0 commit comments