@@ -640,7 +640,7 @@ impl<'a> Parser<'a> {
640640                    } 
641641                } 
642642                Err ( mut  err)  => { 
643-                     // We could 't parse generic parameters, unlikely to be a turbofish. Rely on 
643+                     // We couldn 't parse generic parameters, unlikely to be a turbofish. Rely on 
644644                    // generic parse error instead. 
645645                    err. cancel ( ) ; 
646646                    * self  = snapshot; 
@@ -1242,7 +1242,7 @@ impl<'a> Parser<'a> {
12421242        let  is_question = self . eat ( & token:: Question ) ;  // Handle `await? <expr>`. 
12431243        let  expr = if  self . token  == token:: OpenDelim ( token:: Brace )  { 
12441244            // Handle `await { <expr> }`. 
1245-             // This needs to be handled separatedly  from the next arm to avoid 
1245+             // This needs to be handled separately  from the next arm to avoid 
12461246            // interpreting `await { <expr> }?` as `<expr>?.await`. 
12471247            self . parse_block_expr ( None ,  self . token . span ,  BlockCheckMode :: Default ,  AttrVec :: new ( ) ) 
12481248        }  else  { 
@@ -1613,42 +1613,82 @@ impl<'a> Parser<'a> {
16131613                Applicability :: HasPlaceholders , 
16141614            ) ; 
16151615            return  Some ( ident) ; 
1616-         }  else  if  let  PatKind :: Ident ( _,  ident,  _)  = pat. kind  { 
1617-             if  require_name
1618-                 && ( self . token  == token:: Comma 
1619-                     || self . token  == token:: Lt 
1620-                     || self . token  == token:: CloseDelim ( token:: Paren ) ) 
1621-             { 
1622-                 // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}` 
1623-                 if  first_param { 
1624-                     err. span_suggestion ( 
1625-                         pat. span , 
1626-                         "if this is a `self` type, give it a parameter name" , 
1627-                         format ! ( "self: {}" ,  ident) , 
1628-                         Applicability :: MaybeIncorrect , 
1629-                     ) ; 
1616+         }  else  if  require_name
1617+             && ( self . token  == token:: Comma 
1618+                 || self . token  == token:: Lt 
1619+                 || self . token  == token:: CloseDelim ( token:: Paren ) ) 
1620+         { 
1621+             let  rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)" ; 
1622+ 
1623+             let  ( ident,  self_sugg,  param_sugg,  type_sugg)  = match  pat. kind  { 
1624+                 PatKind :: Ident ( _,  ident,  _)  => ( 
1625+                     ident, 
1626+                     format ! ( "self: {}" ,  ident) , 
1627+                     format ! ( "{}: TypeName" ,  ident) , 
1628+                     format ! ( "_: {}" ,  ident) , 
1629+                 ) , 
1630+                 // Also catches `fn foo(&a)`. 
1631+                 PatKind :: Ref ( ref  pat,  mutab) 
1632+                     if  matches ! ( pat. clone( ) . into_inner( ) . kind,  PatKind :: Ident ( ..) )  =>
1633+                 { 
1634+                     match  pat. clone ( ) . into_inner ( ) . kind  { 
1635+                         PatKind :: Ident ( _,  ident,  _)  => { 
1636+                             let  mutab = mutab. prefix_str ( ) ; 
1637+                             ( 
1638+                                 ident, 
1639+                                 format ! ( "self: &{}{}" ,  mutab,  ident) , 
1640+                                 format ! ( "{}: &{}TypeName" ,  ident,  mutab) , 
1641+                                 format ! ( "_: &{}{}" ,  mutab,  ident) , 
1642+                             ) 
1643+                         } 
1644+                         _ => unreachable ! ( ) , 
1645+                     } 
16301646                } 
1631-                 // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to 
1632-                 // `fn foo(HashMap: TypeName<u32>)`. 
1633-                 if  self . token  != token:: Lt  { 
1634-                     err. span_suggestion ( 
1635-                         pat. span , 
1636-                         "if this is a parameter name, give it a type" , 
1637-                         format ! ( "{}: TypeName" ,  ident) , 
1638-                         Applicability :: HasPlaceholders , 
1639-                     ) ; 
1647+                 _ => { 
1648+                     // Otherwise, try to get a type and emit a suggestion. 
1649+                     if  let  Some ( ty)  = pat. to_ty ( )  { 
1650+                         err. span_suggestion_verbose ( 
1651+                             pat. span , 
1652+                             "explicitly ignore the parameter name" , 
1653+                             format ! ( "_: {}" ,  pprust:: ty_to_string( & ty) ) , 
1654+                             Applicability :: MachineApplicable , 
1655+                         ) ; 
1656+                         err. note ( rfc_note) ; 
1657+                     } 
1658+ 
1659+                     return  None ; 
16401660                } 
1661+             } ; 
1662+ 
1663+             // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}` 
1664+             if  first_param { 
16411665                err. span_suggestion ( 
16421666                    pat. span , 
1643-                     "if this is a type, explicitly ignore the  parameter name" , 
1644-                     format ! ( "_: {}" ,  ident ) , 
1645-                     Applicability :: MachineApplicable , 
1667+                     "if this is a `self`  type, give it a  parameter name" , 
1668+                     self_sugg , 
1669+                     Applicability :: MaybeIncorrect , 
16461670                ) ; 
1647-                 err. note ( "anonymous parameters are removed in the 2018 edition (see RFC 1685)" ) ; 
1648- 
1649-                 // Don't attempt to recover by using the `X` in `X<Y>` as the parameter name. 
1650-                 return  if  self . token  == token:: Lt  {  None  }  else  {  Some ( ident)  } ; 
16511671            } 
1672+             // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to 
1673+             // `fn foo(HashMap: TypeName<u32>)`. 
1674+             if  self . token  != token:: Lt  { 
1675+                 err. span_suggestion ( 
1676+                     pat. span , 
1677+                     "if this is a parameter name, give it a type" , 
1678+                     param_sugg, 
1679+                     Applicability :: HasPlaceholders , 
1680+                 ) ; 
1681+             } 
1682+             err. span_suggestion ( 
1683+                 pat. span , 
1684+                 "if this is a type, explicitly ignore the parameter name" , 
1685+                 type_sugg, 
1686+                 Applicability :: MachineApplicable , 
1687+             ) ; 
1688+             err. note ( rfc_note) ; 
1689+ 
1690+             // Don't attempt to recover by using the `X` in `X<Y>` as the parameter name. 
1691+             return  if  self . token  == token:: Lt  {  None  }  else  {  Some ( ident)  } ; 
16521692        } 
16531693        None 
16541694    } 
0 commit comments