Auto merge of #4450 - phansch:fix_const_fn_fp, r=flip1995
Fix missing_const_for_fn false positive We don't want to lint if the type of the method implements drop. (constant functions cannot evaluate destructors) changelog: Fix `missing_const_for_fn` false positive Fixes #4449
This commit is contained in:
commit
28a8a6a483
@ -1,10 +1,11 @@
|
||||
use crate::utils::{is_entrypoint_fn, span_lint, trait_ref_of_method};
|
||||
use crate::utils::{has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method};
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::FnKind;
|
||||
use rustc::hir::{Body, Constness, FnDecl, HirId};
|
||||
use rustc::hir::{Body, Constness, FnDecl, HirId, HirVec};
|
||||
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn;
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
use syntax_pos::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
@ -94,7 +95,10 @@ fn check_fn(
|
||||
}
|
||||
},
|
||||
FnKind::Method(_, sig, ..) => {
|
||||
if trait_ref_of_method(cx, hir_id).is_some() || already_const(sig.header) {
|
||||
if trait_ref_of_method(cx, hir_id).is_some()
|
||||
|| already_const(sig.header)
|
||||
|| method_accepts_dropable(cx, &sig.decl.inputs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
},
|
||||
@ -113,6 +117,16 @@ fn check_fn(
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if any of the method parameters is a type that implements `Drop`. The method
|
||||
/// can't be made const then, because `drop` can't be const-evaluated.
|
||||
fn method_accepts_dropable(cx: &LateContext<'_, '_>, param_tys: &HirVec<hir::Ty>) -> bool {
|
||||
// If any of the params are dropable, return true
|
||||
param_tys.iter().any(|hir_ty| {
|
||||
let ty_ty = hir_ty_to_ty(cx.tcx, hir_ty);
|
||||
has_drop(cx, ty_ty)
|
||||
})
|
||||
}
|
||||
|
||||
// We don't have to lint on something that's already `const`
|
||||
fn already_const(header: hir::FnHeader) -> bool {
|
||||
header.constness == Constness::Const
|
||||
|
@ -68,3 +68,25 @@ fn add(self, other: Self) -> Self {
|
||||
Point(self.0 + other.0, self.1 + other.1)
|
||||
}
|
||||
}
|
||||
|
||||
mod with_drop {
|
||||
pub struct A;
|
||||
pub struct B;
|
||||
impl Drop for A {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl A {
|
||||
// This can not be const because the type implements `Drop`.
|
||||
pub fn a(self) -> B {
|
||||
B
|
||||
}
|
||||
}
|
||||
|
||||
impl B {
|
||||
// This can not be const because `a` implements `Drop`.
|
||||
pub fn a(self, a: A) -> B {
|
||||
B
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,5 +53,20 @@ fn sub(x: u32) -> usize {
|
||||
t[0]
|
||||
}
|
||||
|
||||
mod with_drop {
|
||||
pub struct A;
|
||||
pub struct B;
|
||||
impl Drop for A {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl B {
|
||||
// This can be const, because `a` is passed by reference
|
||||
pub fn b(self, a: &A) -> B {
|
||||
B
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Should not be const
|
||||
fn main() {}
|
||||
|
@ -49,5 +49,13 @@ LL | | t
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: this could be a const_fn
|
||||
--> $DIR/could_be_const.rs:65:9
|
||||
|
|
||||
LL | / pub fn b(self, a: &A) -> B {
|
||||
LL | | B
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user