@@ -1922,39 +1922,31 @@ fn report_bivariance<'tcx>(
19221922 ) ;
19231923
19241924 if !usage_spans. is_empty ( ) {
1925- // First, check if the ADT is (probably) cyclical. We say probably here, since
1926- // we're not actually looking into substitutions, just walking through fields.
1927- // And we only recurse into the fields of ADTs, and not the hidden types of
1928- // opaques or anything else fancy.
1925+ // First, check if the ADT/LTA is (probably) cyclical. We say probably here, since we're
1926+ // not actually looking into substitutions, just walking through fields / the "RHS".
1927+ // We don't recurse into the hidden types of opaques or anything else fancy.
19291928 let item_def_id = item. owner_id . to_def_id ( ) ;
1930- let is_probably_cyclical = if matches ! (
1931- tcx. def_kind( item_def_id) ,
1932- DefKind :: Struct | DefKind :: Union | DefKind :: Enum
1933- ) {
1934- IsProbablyCyclical { tcx, adt_def_id : item_def_id, seen : Default :: default ( ) }
1935- . visit_all_fields ( tcx. adt_def ( item_def_id) )
1936- . is_break ( )
1937- } else {
1938- false
1939- } ;
1940- // If the ADT is cyclical, then if at least one usage of the type parameter or
1941- // the `Self` alias is present in the, then it's probably a cyclical struct, and
1942- // we should call those parameter usages recursive rather than just saying they're
1943- // unused...
1929+ let is_probably_cyclical =
1930+ IsProbablyCyclical { tcx, item_def_id, seen : Default :: default ( ) }
1931+ . visit_def ( item_def_id)
1932+ . is_break ( ) ;
1933+ // If the ADT/LTA is cyclical, then if at least one usage of the type parameter or
1934+ // the `Self` alias is present in the, then it's probably a cyclical struct/ type
1935+ // alias, and we should call those parameter usages recursive rather than just saying
1936+ // they're unused...
19441937 //
19451938 // We currently report *all* of the parameter usages, since computing the exact
19461939 // subset is very involved, and the fact we're mentioning recursion at all is
19471940 // likely to guide the user in the right direction.
19481941 if is_probably_cyclical {
1949- let diag = tcx. dcx ( ) . create_err ( errors:: RecursiveGenericParameter {
1942+ return tcx. dcx ( ) . emit_err ( errors:: RecursiveGenericParameter {
19501943 spans : usage_spans,
19511944 param_span : param. span ,
19521945 param_name,
19531946 param_def_kind : tcx. def_descr ( param. def_id . to_def_id ( ) ) ,
19541947 help,
19551948 note : ( ) ,
19561949 } ) ;
1957- return diag. emit ( ) ;
19581950 }
19591951 }
19601952
@@ -1974,42 +1966,51 @@ fn report_bivariance<'tcx>(
19741966 diag. emit ( )
19751967}
19761968
1977- /// Detects cases where an ADT is trivially cyclical -- we want to detect this so
1978- /// / we only mention that its parameters are used cyclically if the ADT is truly
1969+ /// Detects cases where an ADT/LTA is trivially cyclical -- we want to detect this so
1970+ /// we only mention that its parameters are used cyclically if the ADT/LTA is truly
19791971/// cyclical.
19801972///
19811973/// Notably, we don't consider substitutions here, so this may have false positives.
19821974struct IsProbablyCyclical < ' tcx > {
19831975 tcx : TyCtxt < ' tcx > ,
1984- adt_def_id : DefId ,
1976+ item_def_id : DefId ,
19851977 seen : FxHashSet < DefId > ,
19861978}
19871979
19881980impl < ' tcx > IsProbablyCyclical < ' tcx > {
1989- fn visit_all_fields ( & mut self , adt_def : ty:: AdtDef < ' tcx > ) -> ControlFlow < ( ) , ( ) > {
1990- for field in adt_def. all_fields ( ) {
1991- self . tcx . type_of ( field. did ) . instantiate_identity ( ) . visit_with ( self ) ?;
1981+ fn visit_def ( & mut self , def_id : DefId ) -> ControlFlow < ( ) , ( ) > {
1982+ match self . tcx . def_kind ( def_id) {
1983+ DefKind :: Struct | DefKind :: Enum | DefKind :: Union => {
1984+ self . tcx . adt_def ( def_id) . all_fields ( ) . try_for_each ( |field| {
1985+ self . tcx . type_of ( field. did ) . instantiate_identity ( ) . visit_with ( self )
1986+ } )
1987+ }
1988+ DefKind :: TyAlias if self . tcx . type_alias_is_lazy ( def_id) => {
1989+ self . tcx . type_of ( def_id) . instantiate_identity ( ) . visit_with ( self )
1990+ }
1991+ _ => ControlFlow :: Continue ( ( ) ) ,
19921992 }
1993-
1994- ControlFlow :: Continue ( ( ) )
19951993 }
19961994}
19971995
19981996impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for IsProbablyCyclical < ' tcx > {
19991997 type Result = ControlFlow < ( ) , ( ) > ;
20001998
2001- fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < ( ) , ( ) > {
2002- if let Some ( adt_def) = t. ty_adt_def ( ) {
2003- if adt_def. did ( ) == self . adt_def_id {
1999+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < ( ) , ( ) > {
2000+ let def_id = match ty. kind ( ) {
2001+ ty:: Adt ( adt_def, _) => Some ( adt_def. did ( ) ) ,
2002+ ty:: Alias ( ty:: Weak , alias_ty) => Some ( alias_ty. def_id ) ,
2003+ _ => None ,
2004+ } ;
2005+ if let Some ( def_id) = def_id {
2006+ if def_id == self . item_def_id {
20042007 return ControlFlow :: Break ( ( ) ) ;
20052008 }
2006-
2007- if self . seen . insert ( adt_def. did ( ) ) {
2008- self . visit_all_fields ( adt_def) ?;
2009+ if self . seen . insert ( def_id) {
2010+ self . visit_def ( def_id) ?;
20092011 }
20102012 }
2011-
2012- t. super_visit_with ( self )
2013+ ty. super_visit_with ( self )
20132014 }
20142015}
20152016
0 commit comments