Skip to content

Commit

Permalink
Rollup merge of rust-lang#102406 - mejrs:missing_copy, r=wesleywiser
Browse files Browse the repository at this point in the history
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?
  • Loading branch information
Dylan-DPC authored Dec 9, 2022
2 parents 14ca83a + 34277fc commit 0f0b4f6
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
32 changes: 31 additions & 1 deletion compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, InnerSpan, Span};
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};

Expand Down Expand Up @@ -750,10 +751,39 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
if def.has_dtor(cx.tcx) {
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();
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
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().build().type_implements_trait(iter_trait, [ty], 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(
cx.tcx,
param_env,
Expand Down
35 changes: 35 additions & 0 deletions src/test/ui/lint/lint-missing-copy-implementations-allow.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 0f0b4f6

Please sign in to comment.