Fix missing_const_for_fn false positive
We don't want to lint if any of the input parameters implement drop. (constant functions cannot evaluate destructors)
This commit is contained in:
parent
4c8a941daf
commit
1b18597554
@ -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 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
|
||||
}
|
||||
},
|
||||
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 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 @@ impl std::ops::Add for Point {
|
||||
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 generic_arr<T: Copy>(t: [T; 1]) -> T {
|
||||
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() {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user