@@ -4,12 +4,12 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
4
4
use crate :: errors;
5
5
use crate :: fluent_generated as fluent;
6
6
7
- use hir:: intravisit:: Visitor ;
7
+ use hir:: intravisit:: { self , Visitor } ;
8
8
use rustc_ast as ast;
9
9
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexSet } ;
10
10
use rustc_errors:: { codes:: * , pluralize, struct_span_code_err, Applicability , ErrorGuaranteed } ;
11
11
use rustc_hir as hir;
12
- use rustc_hir:: def:: DefKind ;
12
+ use rustc_hir:: def:: { DefKind , Res } ;
13
13
use rustc_hir:: def_id:: { DefId , LocalDefId , LocalModDefId } ;
14
14
use rustc_hir:: lang_items:: LangItem ;
15
15
use rustc_hir:: ItemKind ;
@@ -1799,7 +1799,7 @@ fn receiver_is_implemented<'tcx>(
1799
1799
1800
1800
fn check_variances_for_type_defn < ' tcx > (
1801
1801
tcx : TyCtxt < ' tcx > ,
1802
- item : & hir:: Item < ' tcx > ,
1802
+ item : & ' tcx hir:: Item < ' tcx > ,
1803
1803
hir_generics : & hir:: Generics < ' tcx > ,
1804
1804
) {
1805
1805
let identity_args = ty:: GenericArgs :: identity_for_item ( tcx, item. owner_id ) ;
@@ -1886,21 +1886,21 @@ fn check_variances_for_type_defn<'tcx>(
1886
1886
hir:: ParamName :: Error => { }
1887
1887
_ => {
1888
1888
let has_explicit_bounds = explicitly_bounded_params. contains ( & parameter) ;
1889
- report_bivariance ( tcx, hir_param, has_explicit_bounds, item. kind ) ;
1889
+ report_bivariance ( tcx, hir_param, has_explicit_bounds, item) ;
1890
1890
}
1891
1891
}
1892
1892
}
1893
1893
}
1894
1894
1895
- fn report_bivariance (
1896
- tcx : TyCtxt < ' _ > ,
1897
- param : & rustc_hir :: GenericParam < ' _ > ,
1895
+ fn report_bivariance < ' tcx > (
1896
+ tcx : TyCtxt < ' tcx > ,
1897
+ param : & ' tcx hir :: GenericParam < ' tcx > ,
1898
1898
has_explicit_bounds : bool ,
1899
- item_kind : ItemKind < ' _ > ,
1899
+ item : & ' tcx hir :: Item < ' tcx > ,
1900
1900
) -> ErrorGuaranteed {
1901
1901
let param_name = param. name . ident ( ) ;
1902
1902
1903
- let help = match item_kind {
1903
+ let help = match item . kind {
1904
1904
ItemKind :: Enum ( ..) | ItemKind :: Struct ( ..) | ItemKind :: Union ( ..) => {
1905
1905
if let Some ( def_id) = tcx. lang_items ( ) . phantom_data ( ) {
1906
1906
errors:: UnusedGenericParameterHelp :: Adt {
@@ -1915,19 +1915,60 @@ fn report_bivariance(
1915
1915
item_kind => bug ! ( "report_bivariance: unexpected item kind: {item_kind:?}" ) ,
1916
1916
} ;
1917
1917
1918
- let const_param_help =
1919
- matches ! ( param. kind, hir:: GenericParamKind :: Type { .. } if !has_explicit_bounds)
1920
- . then_some ( ( ) ) ;
1918
+ let mut usage_spans = vec ! [ ] ;
1919
+ intravisit:: walk_item (
1920
+ & mut CollectUsageSpans { spans : & mut usage_spans, param_def_id : param. def_id . to_def_id ( ) } ,
1921
+ item,
1922
+ ) ;
1921
1923
1922
- let mut diag = tcx. dcx ( ) . create_err ( errors:: UnusedGenericParameter {
1923
- span : param. span ,
1924
- param_name,
1925
- param_def_kind : tcx. def_descr ( param. def_id . to_def_id ( ) ) ,
1926
- help,
1927
- const_param_help,
1928
- } ) ;
1929
- diag. code ( E0392 ) ;
1930
- diag. emit ( )
1924
+ if usage_spans. is_empty ( ) {
1925
+ let const_param_help =
1926
+ matches ! ( param. kind, hir:: GenericParamKind :: Type { .. } if !has_explicit_bounds)
1927
+ . then_some ( ( ) ) ;
1928
+
1929
+ let mut diag = tcx. dcx ( ) . create_err ( errors:: UnusedGenericParameter {
1930
+ span : param. span ,
1931
+ param_name,
1932
+ param_def_kind : tcx. def_descr ( param. def_id . to_def_id ( ) ) ,
1933
+ help,
1934
+ const_param_help,
1935
+ } ) ;
1936
+ diag. code ( E0392 ) ;
1937
+ diag. emit ( )
1938
+ } else {
1939
+ let diag = tcx. dcx ( ) . create_err ( errors:: RecursiveGenericParameter {
1940
+ spans : usage_spans,
1941
+ param_span : param. span ,
1942
+ param_name,
1943
+ param_def_kind : tcx. def_descr ( param. def_id . to_def_id ( ) ) ,
1944
+ help,
1945
+ note : ( ) ,
1946
+ } ) ;
1947
+ diag. emit ( )
1948
+ }
1949
+ }
1950
+
1951
+ struct CollectUsageSpans < ' a > {
1952
+ spans : & ' a mut Vec < Span > ,
1953
+ param_def_id : DefId ,
1954
+ }
1955
+
1956
+ impl < ' tcx > Visitor < ' tcx > for CollectUsageSpans < ' _ > {
1957
+ type Result = ( ) ;
1958
+
1959
+ fn visit_generics ( & mut self , _g : & ' tcx rustc_hir:: Generics < ' tcx > ) -> Self :: Result {
1960
+ // Skip the generics. We only care about fields, not where clause/param bounds.
1961
+ }
1962
+
1963
+ fn visit_ty ( & mut self , t : & ' tcx hir:: Ty < ' tcx > ) -> Self :: Result {
1964
+ if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , qpath) ) = t. kind
1965
+ && let Res :: Def ( DefKind :: TyParam , def_id) = qpath. res
1966
+ && def_id == self . param_def_id
1967
+ {
1968
+ self . spans . push ( t. span ) ;
1969
+ }
1970
+ intravisit:: walk_ty ( self , t) ;
1971
+ }
1931
1972
}
1932
1973
1933
1974
impl < ' tcx > WfCheckingCtxt < ' _ , ' tcx > {
0 commit comments