@@ -640,7 +640,7 @@ impl<'a> Parser<'a> {
640
640
}
641
641
}
642
642
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
644
644
// generic parse error instead.
645
645
err. cancel ( ) ;
646
646
* self = snapshot;
@@ -1242,7 +1242,7 @@ impl<'a> Parser<'a> {
1242
1242
let is_question = self . eat ( & token:: Question ) ; // Handle `await? <expr>`.
1243
1243
let expr = if self . token == token:: OpenDelim ( token:: Brace ) {
1244
1244
// 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
1246
1246
// interpreting `await { <expr> }?` as `<expr>?.await`.
1247
1247
self . parse_block_expr ( None , self . token . span , BlockCheckMode :: Default , AttrVec :: new ( ) )
1248
1248
} else {
@@ -1613,42 +1613,82 @@ impl<'a> Parser<'a> {
1613
1613
Applicability :: HasPlaceholders ,
1614
1614
) ;
1615
1615
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
+ }
1630
1646
}
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 ;
1640
1660
}
1661
+ } ;
1662
+
1663
+ // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
1664
+ if first_param {
1641
1665
err. span_suggestion (
1642
1666
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 ,
1646
1670
) ;
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) } ;
1651
1671
}
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) } ;
1652
1692
}
1653
1693
None
1654
1694
}
0 commit comments