@@ -8,7 +8,7 @@ use rustc_hir::{
8
8
Body , Expr , ExprKind , GenericArg , Impl , ImplItemKind , Item , ItemKind , Node , PathSegment , QPath , Ty , TyKind ,
9
9
} ;
10
10
use rustc_lint:: { LateContext , LateLintPass } ;
11
- use rustc_middle:: ty:: { AdtDef , DefIdTree } ;
11
+ use rustc_middle:: ty:: { Adt , AdtDef , DefIdTree , SubstsRef } ;
12
12
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
13
13
use rustc_span:: sym;
14
14
@@ -81,13 +81,18 @@ fn check_struct<'tcx>(
81
81
self_ty : & Ty < ' _ > ,
82
82
func_expr : & Expr < ' _ > ,
83
83
adt_def : AdtDef < ' _ > ,
84
+ substs : SubstsRef < ' _ > ,
84
85
) {
85
86
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 paarmeters 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 ;
91
96
}
92
97
}
93
98
}
@@ -184,15 +189,15 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
184
189
if let Some ( Node :: ImplItem ( impl_item) ) = cx. tcx. hir( ) . find( impl_item_hir) ;
185
190
if let ImplItemKind :: Fn ( _, b) = & impl_item. kind;
186
191
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 ( ) ;
188
193
if let attrs = cx. tcx. hir( ) . attrs( item. hir_id( ) ) ;
189
194
if !attrs. iter( ) . any( |attr| attr. doc_str( ) . is_some( ) ) ;
190
195
if let child_attrs = cx. tcx. hir( ) . attrs( impl_item_hir) ;
191
196
if !child_attrs. iter( ) . any( |attr| attr. doc_str( ) . is_some( ) ) ;
192
197
193
198
then {
194
199
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 ) ;
196
201
} else if adt_def. is_enum( ) && self . msrv. meets( msrvs:: DEFAULT_ENUM_ATTRIBUTE ) {
197
202
check_enum( cx, item, func_expr, adt_def) ;
198
203
}
0 commit comments