@@ -25,8 +25,7 @@ use rustc_hir as hir;
25
25
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
26
26
use rustc_hir:: { Node , QPath , TyKind , WhereBoundPredicate , WherePredicate } ;
27
27
use rustc_session:: DiagnosticMessageId ;
28
- use rustc_span:: source_map:: SourceMap ;
29
- use rustc_span:: { ExpnKind , Span , DUMMY_SP } ;
28
+ use rustc_span:: { BytePos , ExpnKind , Span , DUMMY_SP } ;
30
29
use std:: fmt;
31
30
32
31
use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
@@ -1679,14 +1678,8 @@ pub fn suggest_constraining_type_param(
1679
1678
err : & mut DiagnosticBuilder < ' _ > ,
1680
1679
param_name : & str ,
1681
1680
constraint : & str ,
1682
- source_map : & SourceMap ,
1683
- span : Span ,
1684
1681
def_id : Option < DefId > ,
1685
1682
) -> bool {
1686
- const MSG_RESTRICT_BOUND_FURTHER : & str = "consider further restricting this bound with" ;
1687
- const MSG_RESTRICT_TYPE : & str = "consider restricting this type parameter with" ;
1688
- const MSG_RESTRICT_TYPE_FURTHER : & str = "consider further restricting this type parameter with" ;
1689
-
1690
1683
let param = generics. params . iter ( ) . find ( |p| p. name . ident ( ) . as_str ( ) == param_name) ;
1691
1684
1692
1685
let param = if let Some ( param) = param {
@@ -1695,11 +1688,24 @@ pub fn suggest_constraining_type_param(
1695
1688
return false ;
1696
1689
} ;
1697
1690
1691
+ const MSG_RESTRICT_BOUND_FURTHER : & str = "consider further restricting this bound" ;
1692
+ let msg_restrict_type = format ! ( "consider restricting type parameter `{}`" , param_name) ;
1693
+ let msg_restrict_type_further =
1694
+ format ! ( "consider further restricting type parameter `{}`" , param_name) ;
1695
+
1698
1696
if def_id == tcx. lang_items ( ) . sized_trait ( ) {
1699
1697
// Type parameters are already `Sized` by default.
1700
1698
err. span_label ( param. span , & format ! ( "this type parameter needs to be `{}`" , constraint) ) ;
1701
1699
return true ;
1702
1700
}
1701
+ let mut suggest_restrict = |span| {
1702
+ err. span_suggestion_verbose (
1703
+ span,
1704
+ MSG_RESTRICT_BOUND_FURTHER ,
1705
+ format ! ( " + {}" , constraint) ,
1706
+ Applicability :: MachineApplicable ,
1707
+ ) ;
1708
+ } ;
1703
1709
1704
1710
if param_name. starts_with ( "impl " ) {
1705
1711
// If there's an `impl Trait` used in argument position, suggest
@@ -1717,19 +1723,15 @@ pub fn suggest_constraining_type_param(
1717
1723
// |
1718
1724
// replace with: `impl Foo + Bar`
1719
1725
1720
- err. span_help ( param. span , & format ! ( "{} `+ {}`" , MSG_RESTRICT_BOUND_FURTHER , constraint) ) ;
1721
-
1722
- err. tool_only_span_suggestion (
1723
- param. span ,
1724
- MSG_RESTRICT_BOUND_FURTHER ,
1725
- format ! ( "{} + {}" , param_name, constraint) ,
1726
- Applicability :: MachineApplicable ,
1727
- ) ;
1728
-
1726
+ suggest_restrict ( param. span . shrink_to_hi ( ) ) ;
1729
1727
return true ;
1730
1728
}
1731
1729
1732
- if generics. where_clause . predicates . is_empty ( ) {
1730
+ if generics. where_clause . predicates . is_empty ( )
1731
+ // Given `trait Base<T = String>: Super<T>` where `T: Copy`, suggest restricting in the
1732
+ // `where` clause instead of `trait Base<T: Copy = String>: Super<T>`.
1733
+ && !matches ! ( param. kind, hir:: GenericParamKind :: Type { default : Some ( _) , .. } )
1734
+ {
1733
1735
if let Some ( bounds_span) = param. bounds_span ( ) {
1734
1736
// If user has provided some bounds, suggest restricting them:
1735
1737
//
@@ -1744,38 +1746,16 @@ pub fn suggest_constraining_type_param(
1744
1746
// --
1745
1747
// |
1746
1748
// replace with: `T: Bar +`
1747
-
1748
- err. span_help (
1749
- bounds_span,
1750
- & format ! ( "{} `+ {}`" , MSG_RESTRICT_BOUND_FURTHER , constraint) ,
1751
- ) ;
1752
-
1753
- let span_hi = param. span . with_hi ( span. hi ( ) ) ;
1754
- let span_with_colon = source_map. span_through_char ( span_hi, ':' ) ;
1755
-
1756
- if span_hi != param. span && span_with_colon != span_hi {
1757
- err. tool_only_span_suggestion (
1758
- span_with_colon,
1759
- MSG_RESTRICT_BOUND_FURTHER ,
1760
- format ! ( "{}: {} + " , param_name, constraint) ,
1761
- Applicability :: MachineApplicable ,
1762
- ) ;
1763
- }
1749
+ suggest_restrict ( bounds_span. shrink_to_hi ( ) ) ;
1764
1750
} else {
1765
1751
// If user hasn't provided any bounds, suggest adding a new one:
1766
1752
//
1767
1753
// fn foo<T>(t: T) { ... }
1768
1754
// - help: consider restricting this type parameter with `T: Foo`
1769
-
1770
- err. span_help (
1771
- param. span ,
1772
- & format ! ( "{} `{}: {}`" , MSG_RESTRICT_TYPE , param_name, constraint) ,
1773
- ) ;
1774
-
1775
- err. tool_only_span_suggestion (
1776
- param. span ,
1777
- MSG_RESTRICT_TYPE ,
1778
- format ! ( "{}: {}" , param_name, constraint) ,
1755
+ err. span_suggestion_verbose (
1756
+ param. span . shrink_to_hi ( ) ,
1757
+ & msg_restrict_type,
1758
+ format ! ( ": {}" , constraint) ,
1779
1759
Applicability :: MachineApplicable ,
1780
1760
) ;
1781
1761
}
@@ -1839,55 +1819,25 @@ pub fn suggest_constraining_type_param(
1839
1819
}
1840
1820
}
1841
1821
1842
- let where_clause_span =
1843
- generics. where_clause . span_for_predicates_or_empty_place ( ) . shrink_to_hi ( ) ;
1822
+ let where_clause_span = generics. where_clause . span_for_predicates_or_empty_place ( ) ;
1823
+ // Account for `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
1824
+ let mut trailing_comma = false ;
1825
+ if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( where_clause_span) {
1826
+ trailing_comma = snippet. ends_with ( "," ) ;
1827
+ }
1828
+ let where_clause_span = if trailing_comma {
1829
+ let hi = where_clause_span. hi ( ) ;
1830
+ Span :: new ( hi - BytePos ( 1 ) , hi, where_clause_span. ctxt ( ) )
1831
+ } else {
1832
+ where_clause_span. shrink_to_hi ( )
1833
+ } ;
1844
1834
1845
1835
match & param_spans[ ..] {
1846
- & [ ] => {
1847
- err. span_help (
1848
- param. span ,
1849
- & format ! ( "{} `where {}: {}`" , MSG_RESTRICT_TYPE , param_name, constraint) ,
1850
- ) ;
1851
-
1852
- err. tool_only_span_suggestion (
1853
- where_clause_span,
1854
- MSG_RESTRICT_TYPE ,
1855
- format ! ( ", {}: {}" , param_name, constraint) ,
1856
- Applicability :: MachineApplicable ,
1857
- ) ;
1858
- }
1859
-
1860
- & [ & param_span] => {
1861
- err. span_help (
1862
- param_span,
1863
- & format ! ( "{} `+ {}`" , MSG_RESTRICT_BOUND_FURTHER , constraint) ,
1864
- ) ;
1865
-
1866
- let span_hi = param_span. with_hi ( span. hi ( ) ) ;
1867
- let span_with_colon = source_map. span_through_char ( span_hi, ':' ) ;
1868
-
1869
- if span_hi != param_span && span_with_colon != span_hi {
1870
- err. tool_only_span_suggestion (
1871
- span_with_colon,
1872
- MSG_RESTRICT_BOUND_FURTHER ,
1873
- format ! ( "{}: {} +" , param_name, constraint) ,
1874
- Applicability :: MachineApplicable ,
1875
- ) ;
1876
- }
1877
- }
1878
-
1836
+ & [ & param_span] => suggest_restrict ( param_span. shrink_to_hi ( ) ) ,
1879
1837
_ => {
1880
- err. span_help (
1881
- param. span ,
1882
- & format ! (
1883
- "{} `where {}: {}`" ,
1884
- MSG_RESTRICT_TYPE_FURTHER , param_name, constraint,
1885
- ) ,
1886
- ) ;
1887
-
1888
- err. tool_only_span_suggestion (
1838
+ err. span_suggestion_verbose (
1889
1839
where_clause_span,
1890
- MSG_RESTRICT_BOUND_FURTHER ,
1840
+ & msg_restrict_type_further ,
1891
1841
format ! ( ", {}: {}" , param_name, constraint) ,
1892
1842
Applicability :: MachineApplicable ,
1893
1843
) ;
0 commit comments