@@ -14,7 +14,7 @@ use crate::ThinVec;
1414use crate :: util:: parser:: AssocOp ;
1515use errors:: { Applicability , DiagnosticBuilder , DiagnosticId } ;
1616use rustc_data_structures:: fx:: FxHashSet ;
17- use syntax_pos:: { Span , DUMMY_SP , MultiSpan } ;
17+ use syntax_pos:: { Span , DUMMY_SP , MultiSpan , SpanSnippetError } ;
1818use log:: { debug, trace} ;
1919use std:: mem;
2020
@@ -199,6 +199,10 @@ impl<'a> Parser<'a> {
199199 & self . sess . span_diagnostic
200200 }
201201
202+ crate fn span_to_snippet ( & self , span : Span ) -> Result < String , SpanSnippetError > {
203+ self . sess . source_map ( ) . span_to_snippet ( span)
204+ }
205+
202206 crate fn expected_ident_found ( & self ) -> DiagnosticBuilder < ' a > {
203207 let mut err = self . struct_span_err (
204208 self . token . span ,
@@ -549,8 +553,10 @@ impl<'a> Parser<'a> {
549553 ExprKind :: Binary ( op, _, _) if op. node . is_comparison ( ) => {
550554 // respan to include both operators
551555 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+ ) ;
554560 if op. node == BinOpKind :: Lt &&
555561 * outer_op == AssocOp :: Less || // Include `<` to provide this recommendation
556562 * outer_op == AssocOp :: Greater // even in a case like the following:
@@ -717,8 +723,6 @@ impl<'a> Parser<'a> {
717723 path. span = ty_span. to ( self . prev_span ) ;
718724
719725 let ty_str = self
720- . sess
721- . source_map ( )
722726 . span_to_snippet ( ty_span)
723727 . unwrap_or_else ( |_| pprust:: ty_to_string ( & ty) ) ;
724728 self . diagnostic ( )
@@ -889,7 +893,7 @@ impl<'a> Parser<'a> {
889893 err. span_label ( await_sp, "while parsing this incorrect await expression" ) ;
890894 err
891895 } ) ?;
892- let expr_str = self . sess . source_map ( ) . span_to_snippet ( expr. span )
896+ let expr_str = self . span_to_snippet ( expr. span )
893897 . unwrap_or_else ( |_| pprust:: expr_to_string ( & expr) ) ;
894898 let suggestion = format ! ( "{}.await{}" , expr_str, if is_question { "?" } else { "" } ) ;
895899 let sp = lo. to ( expr. span ) ;
@@ -923,6 +927,48 @@ impl<'a> Parser<'a> {
923927 }
924928 }
925929
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+
926972 crate fn could_ascription_be_path ( & self , node : & ast:: ExprKind ) -> bool {
927973 self . token . is_ident ( ) &&
928974 if let ast:: ExprKind :: Path ( ..) = node { true } else { false } &&
@@ -1105,17 +1151,14 @@ impl<'a> Parser<'a> {
11051151 crate fn check_for_for_in_in_typo ( & mut self , in_span : Span ) {
11061152 if self . eat_keyword ( kw:: In ) {
11071153 // 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 ( ) ;
11191162 }
11201163 }
11211164
@@ -1128,12 +1171,12 @@ impl<'a> Parser<'a> {
11281171
11291172 crate fn eat_incorrect_doc_comment_for_arg_type ( & mut self ) {
11301173 if let token:: DocComment ( _) = self . token . kind {
1131- let mut err = self . diagnostic ( ) . struct_span_err (
1174+ self . struct_span_err (
11321175 self . token . span ,
11331176 "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 ( ) ;
11371180 self . bump ( ) ;
11381181 } else if self . token == token:: Pound && self . look_ahead ( 1 , |t| {
11391182 * t == token:: OpenDelim ( token:: Bracket )
@@ -1145,12 +1188,12 @@ impl<'a> Parser<'a> {
11451188 }
11461189 let sp = lo. to ( self . token . span ) ;
11471190 self . bump ( ) ;
1148- let mut err = self . diagnostic ( ) . struct_span_err (
1191+ self . struct_span_err (
11491192 sp,
11501193 "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 ( ) ;
11541197 }
11551198 }
11561199
@@ -1206,18 +1249,19 @@ impl<'a> Parser<'a> {
12061249 self . expect ( & token:: Colon ) ?;
12071250 let ty = self . parse_ty ( ) ?;
12081251
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 ( ) ;
12211265
12221266 // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
12231267 let pat = P ( Pat {
0 commit comments