@@ -8,7 +8,7 @@ use rustc_hir::{
88 Body , Expr , ExprKind , GenericArg , Impl , ImplItemKind , Item , ItemKind , Node , PathSegment , QPath , Ty , TyKind ,
99} ;
1010use rustc_lint:: { LateContext , LateLintPass } ;
11- use rustc_middle:: ty:: { AdtDef , DefIdTree } ;
11+ use rustc_middle:: ty:: { Adt , AdtDef , DefIdTree , SubstsRef } ;
1212use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
1313use rustc_span:: sym;
1414
@@ -81,13 +81,18 @@ fn check_struct<'tcx>(
8181 self_ty : & Ty < ' _ > ,
8282 func_expr : & Expr < ' _ > ,
8383 adt_def : AdtDef < ' _ > ,
84+ substs : SubstsRef < ' _ > ,
8485) {
8586 if let TyKind :: Path ( QPath :: Resolved ( _, p) ) = self_ty. kind {
86- if let Some ( PathSegment { args : Some ( a) , .. } ) = p. segments . last ( ) {
87- for arg in a. args {
88- if !matches ! ( arg, GenericArg :: Lifetime ( _) ) {
89- return ;
90- }
87+ if let Some ( PathSegment { args, .. } ) = p. segments . last ( ) {
88+ let args = args. map ( |a| a. args ) . unwrap_or ( & [ ] ) ;
89+
90+ // substs contains the generic parameters of the type declaration, while args contains the arguments
91+ // used at instantiation time. If both len are not equal, it means that some parameters were not
92+ // provided (which means that the default values were used); in this case we will not risk
93+ // suggesting too broad a rewrite. We won't either if any argument is a type or a const.
94+ if substs. len ( ) != args. len ( ) || args. iter ( ) . any ( |arg| !matches ! ( arg, GenericArg :: Lifetime ( _) ) ) {
95+ return ;
9196 }
9297 }
9398 }
@@ -184,15 +189,15 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
184189 if let Some ( Node :: ImplItem ( impl_item) ) = cx. tcx. hir( ) . find( impl_item_hir) ;
185190 if let ImplItemKind :: Fn ( _, b) = & impl_item. kind;
186191 if let Body { value: func_expr, .. } = cx. tcx. hir( ) . body( * b) ;
187- if let Some ( adt_def) = cx. tcx. type_of( item. owner_id) . subst_identity( ) . ty_adt_def ( ) ;
192+ if let & Adt ( adt_def, substs ) = cx. tcx. type_of( item. owner_id) . subst_identity( ) . kind ( ) ;
188193 if let attrs = cx. tcx. hir( ) . attrs( item. hir_id( ) ) ;
189194 if !attrs. iter( ) . any( |attr| attr. doc_str( ) . is_some( ) ) ;
190195 if let child_attrs = cx. tcx. hir( ) . attrs( impl_item_hir) ;
191196 if !child_attrs. iter( ) . any( |attr| attr. doc_str( ) . is_some( ) ) ;
192197
193198 then {
194199 if adt_def. is_struct( ) {
195- check_struct( cx, item, self_ty, func_expr, adt_def) ;
200+ check_struct( cx, item, self_ty, func_expr, adt_def, substs ) ;
196201 } else if adt_def. is_enum( ) && self . msrv. meets( msrvs:: DEFAULT_ENUM_ATTRIBUTE ) {
197202 check_enum( cx, item, func_expr, adt_def) ;
198203 }
0 commit comments