Skip to content

Commit 0f0b4f6

Browse files
authored
Rollup merge of rust-lang#102406 - mejrs:missing_copy, r=wesleywiser
Make `missing_copy_implementations` more cautious - Fixes rust-lang#98348 - Also makes the lint not fire on large types and types containing raw pointers. Thoughts?
2 parents 14ca83a + 34277fc commit 0f0b4f6

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

compiler/rustc_lint/src/builtin.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ use rustc_span::source_map::Spanned;
5353
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5454
use rustc_span::{BytePos, InnerSpan, Span};
5555
use rustc_target::abi::{Abi, VariantIdx};
56-
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
56+
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
57+
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
5758

5859
use crate::nonstandard_style::{method_context, MethodLateContext};
5960

@@ -750,10 +751,39 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
750751
if def.has_dtor(cx.tcx) {
751752
return;
752753
}
754+
755+
// If the type contains a raw pointer, it may represent something like a handle,
756+
// and recommending Copy might be a bad idea.
757+
for field in def.all_fields() {
758+
let did = field.did;
759+
if cx.tcx.type_of(did).is_unsafe_ptr() {
760+
return;
761+
}
762+
}
753763
let param_env = ty::ParamEnv::empty();
754764
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
755765
return;
756766
}
767+
768+
// We shouldn't recommend implementing `Copy` on stateful things,
769+
// such as iterators.
770+
if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) {
771+
if cx.tcx.infer_ctxt().build().type_implements_trait(iter_trait, [ty], 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+
757787
if can_type_implement_copy(
758788
cx.tcx,
759789
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)