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} ;
22use rustc:: hir;
33use rustc:: hir:: intravisit:: FnKind ;
4- use rustc:: hir:: { Body , Constness , FnDecl , HirId } ;
4+ use rustc:: hir:: { Body , Constness , FnDecl , HirId , HirVec } ;
55use rustc:: lint:: { in_external_macro, LateContext , LateLintPass , LintArray , LintPass } ;
66use rustc:: { declare_lint_pass, declare_tool_lint} ;
77use rustc_mir:: transform:: qualify_min_const_fn:: is_min_const_fn;
8+ use rustc_typeck:: hir_ty_to_ty;
89use syntax_pos:: Span ;
910
1011declare_clippy_lint ! {
@@ -94,7 +95,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
9495 }
9596 } ,
9697 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+ {
98102 return ;
99103 }
100104 } ,
@@ -113,6 +117,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
113117 }
114118}
115119
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+
116130// We don't have to lint on something that's already `const`
117131fn already_const ( header : hir:: FnHeader ) -> bool {
118132 header. constness == Constness :: Const
0 commit comments