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