Skip to content

Commit 1ccc2ab

Browse files
author
mejrs
committed
Make missing_copy_implementations more cautious
1 parent 837bf37 commit 1ccc2ab

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

compiler/rustc_lint/src/builtin.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,16 @@ use rustc_middle::lint::in_external_macro;
4646
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
4747
use rustc_middle::ty::print::with_no_trimmed_paths;
4848
use rustc_middle::ty::subst::GenericArgKind;
49+
use rustc_middle::ty::List;
4950
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef};
5051
use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
5152
use rustc_span::edition::Edition;
5253
use rustc_span::source_map::Spanned;
5354
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5455
use rustc_span::{BytePos, InnerSpan, Span};
5556
use rustc_target::abi::VariantIdx;
56-
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
57+
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
58+
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
5759

5860
use crate::nonstandard_style::{method_context, MethodLateContext};
5961

@@ -748,10 +750,40 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
748750
if def.has_dtor(cx.tcx) {
749751
return;
750752
}
753+
754+
// If the type contains a raw pointer, it may represent something like a handle,
755+
// and recommending Copy might be a bad idea.
756+
for field in def.all_fields() {
757+
let did = field.did;
758+
if cx.tcx.type_of(did).is_unsafe_ptr() {
759+
return;
760+
}
761+
}
751762
let param_env = ty::ParamEnv::empty();
752763
if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
753764
return;
754765
}
766+
767+
// We shouldn't recommend implementing `Copy` on stateful things,
768+
// such as iterators.
769+
if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) {
770+
if cx.tcx.infer_ctxt().enter(|infer_ctxt| {
771+
infer_ctxt.type_implements_trait(iter_trait, ty, List::empty(), param_env)
772+
== EvaluationResult::EvaluatedToOk
773+
}) {
774+
return;
775+
}
776+
}
777+
778+
// Default value of clippy::trivially_copy_pass_by_ref
779+
const MAX_SIZE: u64 = 256;
780+
781+
if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) {
782+
if size > MAX_SIZE {
783+
return;
784+
}
785+
}
786+
755787
if can_type_implement_copy(
756788
cx.tcx,
757789
param_env,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// check-pass
2+
#![deny(missing_copy_implementations)]
3+
4+
// Don't recommend implementing Copy on something stateful like an iterator.
5+
pub struct MyIterator {
6+
num: u8,
7+
}
8+
9+
impl Iterator for MyIterator {
10+
type Item = u8;
11+
12+
fn next(&mut self) -> Option<Self::Item> {
13+
todo!()
14+
}
15+
}
16+
17+
pub struct Handle {
18+
inner: *mut (),
19+
}
20+
21+
pub struct Handle2 {
22+
inner: *const (),
23+
}
24+
25+
pub enum MaybeHandle {
26+
Ptr(*mut ()),
27+
}
28+
29+
pub union UnionHandle {
30+
ptr: *mut (),
31+
}
32+
33+
pub struct Array([u8; 2048]);
34+
35+
fn main() {}

0 commit comments

Comments
 (0)