Make missing_copy_implementations more cautious

This commit is contained in:
mejrs 2022-09-28 15:11:27 +02:00
parent c372b14701
commit 4ced370f7c
2 changed files with 68 additions and 1 deletions

View File

@ -46,6 +46,7 @@ use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::layout::{LayoutError, LayoutOf};
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::List;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef};
use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
@ -53,7 +54,8 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, InnerSpan, Span}; use rustc_span::{BytePos, InnerSpan, Span};
use rustc_target::abi::{Abi, VariantIdx}; use rustc_target::abi::{Abi, VariantIdx};
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy}; use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
use crate::nonstandard_style::{method_context, MethodLateContext}; use crate::nonstandard_style::{method_context, MethodLateContext};
@ -750,10 +752,40 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
if def.has_dtor(cx.tcx) { if def.has_dtor(cx.tcx) {
return; return;
} }
// If the type contains a raw pointer, it may represent something like a handle,
// and recommending Copy might be a bad idea.
for field in def.all_fields() {
let did = field.did;
if cx.tcx.type_of(did).is_unsafe_ptr() {
return;
}
}
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
if ty.is_copy_modulo_regions(cx.tcx, param_env) { if ty.is_copy_modulo_regions(cx.tcx, param_env) {
return; return;
} }
// We shouldn't recommend implementing `Copy` on stateful things,
// such as iterators.
if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) {
if cx.tcx.infer_ctxt().enter(|infer_ctxt| {
infer_ctxt.type_implements_trait(iter_trait, ty, List::empty(), param_env)
== EvaluationResult::EvaluatedToOk
}) {
return;
}
}
// Default value of clippy::trivially_copy_pass_by_ref
const MAX_SIZE: u64 = 256;
if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) {
if size > MAX_SIZE {
return;
}
}
if can_type_implement_copy( if can_type_implement_copy(
cx.tcx, cx.tcx,
param_env, param_env,

View File

@ -0,0 +1,35 @@
// check-pass
#![deny(missing_copy_implementations)]
// Don't recommend implementing Copy on something stateful like an iterator.
pub struct MyIterator {
num: u8,
}
impl Iterator for MyIterator {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
pub struct Handle {
inner: *mut (),
}
pub struct Handle2 {
inner: *const (),
}
pub enum MaybeHandle {
Ptr(*mut ()),
}
pub union UnionHandle {
ptr: *mut (),
}
pub struct Array([u8; 2048]);
fn main() {}