diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index cddcba3cb010..0679d7ea9663 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,4 +1,4 @@ -use crate::utils::{has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method}; +use crate::utils::{has_drop, is_entrypoint_fn, return_ty, span_lint, trait_ref_of_method}; use rustc::declare_lint_pass; use rustc::hir; use rustc::hir::intravisit::FnKind; @@ -91,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { // can skip the actual const check and return early. match kind { FnKind::ItemFn(_, _, header, ..) => { - if already_const(header) { + if already_const(header) || returns_dropable(cx, hir_id) { return; } }, @@ -99,6 +99,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { if trait_ref_of_method(cx, hir_id).is_some() || already_const(sig.header) || method_accepts_dropable(cx, sig.decl.inputs) + || returns_dropable(cx, hir_id) { return; } @@ -128,6 +129,11 @@ fn method_accepts_dropable(cx: &LateContext<'_, '_>, param_tys: &[hir::Ty<'_>]) }) } +fn returns_dropable(cx: &LateContext<'_, '_>, ret_ty: hir::HirId) -> bool { + let return_ty = return_ty(cx, ret_ty); + has_drop(cx, return_ty) +} + // We don't have to lint on something that's already `const` #[must_use] fn already_const(header: hir::FnHeader) -> bool { diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index f367279906fd..6228d6ef4e63 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -89,4 +89,29 @@ mod with_drop { B } } + + struct CustomDrop { + field: i32, + } + + impl Drop for CustomDrop { + fn drop(&mut self) {} + } + + struct Bar { + field: CustomDrop, + } + + impl Bar { + fn take(self) -> CustomDrop { + self.field + } + } + + fn take() -> CustomDrop { + let x = Bar { + field: CustomDrop { field: 1 }, + }; + x.field + } }