@@ -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