@@ -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,6 +1688,11 @@ 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) ) ;
@@ -1717,19 +1715,21 @@ pub fn suggest_constraining_type_param(
1717
1715
// |
1718
1716
// replace with: `impl Foo + Bar`
1719
1717
1720
- err. span_help ( param. span , & format ! ( "{} `+ {}`" , MSG_RESTRICT_BOUND_FURTHER , constraint) ) ;
1721
-
1722
- err. tool_only_span_suggestion (
1723
- param. span ,
1718
+ err. span_suggestion_verbose (
1719
+ param. span . shrink_to_hi ( ) ,
1724
1720
MSG_RESTRICT_BOUND_FURTHER ,
1725
- format ! ( "{} + {}" , param_name , constraint) ,
1721
+ format ! ( " + {}" , constraint) ,
1726
1722
Applicability :: MachineApplicable ,
1727
1723
) ;
1728
1724
1729
1725
return true ;
1730
1726
}
1731
1727
1732
- if generics. where_clause . predicates . is_empty ( ) {
1728
+ if generics. where_clause . predicates . is_empty ( )
1729
+ // Given `trait Base<T = String>: Super<T>` where `T: Copy`, suggest restricting in the
1730
+ // `where` clause in stead of `trait Base<T: Copy = String>: Super<T>`.
1731
+ && !matches ! ( param. kind, hir:: GenericParamKind :: Type { default : Some ( _) , .. } )
1732
+ {
1733
1733
if let Some ( bounds_span) = param. bounds_span ( ) {
1734
1734
// If user has provided some bounds, suggest restricting them:
1735
1735
//
@@ -1745,37 +1745,21 @@ pub fn suggest_constraining_type_param(
1745
1745
// |
1746
1746
// replace with: `T: Bar +`
1747
1747
1748
- err. span_help (
1749
- bounds_span,
1750
- & format ! ( "{} `+ {}`" , MSG_RESTRICT_BOUND_FURTHER , constraint) ,
1748
+ err. span_suggestion_verbose (
1749
+ bounds_span. shrink_to_hi ( ) ,
1750
+ MSG_RESTRICT_BOUND_FURTHER ,
1751
+ format ! ( " + {}" , constraint) ,
1752
+ Applicability :: MachineApplicable ,
1751
1753
) ;
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
- }
1764
1754
} else {
1765
1755
// If user hasn't provided any bounds, suggest adding a new one:
1766
1756
//
1767
1757
// fn foo<T>(t: T) { ... }
1768
1758
// - 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) ,
1759
+ err. span_suggestion_verbose (
1760
+ param. span . shrink_to_hi ( ) ,
1761
+ & msg_restrict_type,
1762
+ format ! ( ": {}" , constraint) ,
1779
1763
Applicability :: MachineApplicable ,
1780
1764
) ;
1781
1765
}
@@ -1839,55 +1823,44 @@ pub fn suggest_constraining_type_param(
1839
1823
}
1840
1824
}
1841
1825
1842
- let where_clause_span =
1843
- generics. where_clause . span_for_predicates_or_empty_place ( ) . shrink_to_hi ( ) ;
1826
+ let where_clause_span = generics. where_clause . span_for_predicates_or_empty_place ( ) ;
1827
+ // Account for `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
1828
+ let mut trailing_comma = false ;
1829
+ if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( where_clause_span) {
1830
+ if snippet. ends_with ( "," ) {
1831
+ trailing_comma = true ;
1832
+ }
1833
+ }
1834
+ let where_clause_span = if trailing_comma {
1835
+ let hi = where_clause_span. hi ( ) ;
1836
+ Span :: new ( hi - BytePos ( 1 ) , hi, where_clause_span. ctxt ( ) )
1837
+ } else {
1838
+ where_clause_span. shrink_to_hi ( )
1839
+ } ;
1844
1840
1845
1841
match & param_spans[ ..] {
1846
1842
& [ ] => {
1847
- err. span_help (
1848
- param. span ,
1849
- & format ! ( "{} `where {}: {}`" , MSG_RESTRICT_TYPE , param_name, constraint) ,
1850
- ) ;
1851
-
1852
- err. tool_only_span_suggestion (
1843
+ err. span_suggestion_verbose (
1853
1844
where_clause_span,
1854
- MSG_RESTRICT_TYPE ,
1845
+ & msg_restrict_type_further ,
1855
1846
format ! ( ", {}: {}" , param_name, constraint) ,
1856
1847
Applicability :: MachineApplicable ,
1857
1848
) ;
1858
1849
}
1859
1850
1860
1851
& [ & param_span] => {
1861
- err. span_help (
1862
- param_span,
1863
- & format ! ( "{} `+ {}`" , MSG_RESTRICT_BOUND_FURTHER , constraint) ,
1852
+ err. span_suggestion_verbose (
1853
+ param_span. shrink_to_hi ( ) ,
1854
+ MSG_RESTRICT_BOUND_FURTHER ,
1855
+ format ! ( " + {}" , constraint) ,
1856
+ Applicability :: MachineApplicable ,
1864
1857
) ;
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
1858
}
1878
1859
1879
1860
_ => {
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 (
1861
+ err. span_suggestion_verbose (
1889
1862
where_clause_span,
1890
- MSG_RESTRICT_BOUND_FURTHER ,
1863
+ & msg_restrict_type_further ,
1891
1864
format ! ( ", {}: {}" , param_name, constraint) ,
1892
1865
Applicability :: MachineApplicable ,
1893
1866
) ;
0 commit comments