1
- use crate :: utils:: { is_entrypoint_fn, span_lint, trait_ref_of_method} ;
1
+ use crate :: utils:: { has_drop , is_entrypoint_fn, span_lint, trait_ref_of_method} ;
2
2
use rustc:: hir;
3
3
use rustc:: hir:: intravisit:: FnKind ;
4
- use rustc:: hir:: { Body , Constness , FnDecl , HirId } ;
4
+ use rustc:: hir:: { Body , Constness , FnDecl , HirId , HirVec } ;
5
5
use rustc:: lint:: { in_external_macro, LateContext , LateLintPass , LintArray , LintPass } ;
6
6
use rustc:: { declare_lint_pass, declare_tool_lint} ;
7
7
use rustc_mir:: transform:: qualify_min_const_fn:: is_min_const_fn;
8
+ use rustc_typeck:: hir_ty_to_ty;
8
9
use syntax_pos:: Span ;
9
10
10
11
declare_clippy_lint ! {
@@ -94,7 +95,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
94
95
}
95
96
} ,
96
97
FnKind :: Method ( _, sig, ..) => {
97
- if trait_ref_of_method ( cx, hir_id) . is_some ( ) || already_const ( sig. header ) {
98
+ if trait_ref_of_method ( cx, hir_id) . is_some ( )
99
+ || already_const ( sig. header )
100
+ || method_accepts_dropable ( cx, & sig. decl . inputs )
101
+ {
98
102
return ;
99
103
}
100
104
} ,
@@ -113,6 +117,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
113
117
}
114
118
}
115
119
120
+ /// Returns true if any of the method parameters is a type that implements `Drop`. The method
121
+ /// can't be made const then, because `drop` can't be const-evaluated.
122
+ fn method_accepts_dropable ( cx : & LateContext < ' _ , ' _ > , param_tys : & HirVec < hir:: Ty > ) -> bool {
123
+ // If any of the params are dropable, return true
124
+ param_tys. iter ( ) . any ( |hir_ty| {
125
+ let ty_ty = hir_ty_to_ty ( cx. tcx , hir_ty) ;
126
+ has_drop ( cx, ty_ty)
127
+ } )
128
+ }
129
+
116
130
// We don't have to lint on something that's already `const`
117
131
fn already_const ( header : hir:: FnHeader ) -> bool {
118
132
header. constness == Constness :: Const
0 commit comments