Skip to content

Remove the missing_copy_implementations lint. #126293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ lint_builtin_link_section_fn = declaration of a function with `link_section`

lint_builtin_link_section_static = declaration of a static with `link_section`

lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy`

lint_builtin_missing_debug_impl =
type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation

Expand Down
158 changes: 5 additions & 153 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ use crate::{
BuiltinDerefNullptr, BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
BuiltinMutablesTransmutes, BuiltinNamedAsmLabel, BuiltinNoMangleGeneric,
BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds,
BuiltinTypeAliasGenericBounds, BuiltinTypeAliasGenericBoundsSuggestion,
BuiltinTypeAliasWhereClause, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes,
BuiltinNamedAsmLabel, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds,
BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause,
BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe,
BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
BuiltinWhileTrue, SuggestChangingAssocTypes,
Expand All @@ -54,11 +54,9 @@ use rustc_hir::intravisit::FnKind as HirFnKind;
use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin};
use rustc_middle::bug;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::Upcast;
use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
Expand All @@ -67,9 +65,6 @@ 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;
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
use tracing::debug;

use crate::nonstandard_style::{method_context, MethodLateContext};
Expand Down Expand Up @@ -598,148 +593,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
}

declare_lint! {
/// The `missing_copy_implementations` lint detects potentially-forgotten
/// implementations of [`Copy`] for public types.
///
/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(missing_copy_implementations)]
/// pub struct Foo {
/// pub field: i32
/// }
/// # fn main() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Historically (before 1.0), types were automatically marked as `Copy`
/// if possible. This was changed so that it required an explicit opt-in
/// by implementing the `Copy` trait. As part of this change, a lint was
/// added to alert if a copyable type was not marked `Copy`.
///
/// This lint is "allow" by default because this code isn't bad; it is
/// common to write newtypes like this specifically so that a `Copy` type
/// is no longer `Copy`. `Copy` types can result in unintended copies of
/// large data which can impact performance.
pub MISSING_COPY_IMPLEMENTATIONS,
Allow,
"detects potentially-forgotten implementations of `Copy`"
}

declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]);

impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
return;
}
let (def, ty) = match item.kind {
hir::ItemKind::Struct(_, ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
(def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
}
hir::ItemKind::Union(_, ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
(def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
}
hir::ItemKind::Enum(_, ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
(def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
}
_ => return,
};
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).instantiate_identity().is_unsafe_ptr() {
return;
}
}
if ty.is_copy_modulo_regions(cx.tcx, cx.param_env) {
return;
}
if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.param_env) {
return;
}
if def.is_variant_list_non_exhaustive()
|| def.variants().iter().any(|variant| variant.is_field_list_non_exhaustive())
{
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)
&& cx
.tcx
.infer_ctxt()
.build()
.type_implements_trait(iter_trait, [ty], cx.param_env)
.must_apply_modulo_regions()
{
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 type_allowed_to_implement_copy(
cx.tcx,
cx.param_env,
ty,
traits::ObligationCause::misc(item.span, item.owner_id.def_id),
)
.is_ok()
{
cx.emit_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, BuiltinMissingCopyImpl);
}
}
}

/// Check whether a `ty` has a negative `Copy` implementation, ignoring outlives constraints.
fn type_implements_negative_copy_modulo_regions<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]);
let pred = ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Negative };
let obligation = traits::Obligation {
cause: traits::ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: pred.upcast(tcx),
};

tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
}

declare_lint! {
/// The `missing_debug_implementations` lint detects missing
/// implementations of [`fmt::Debug`] for public types.
Expand Down Expand Up @@ -1644,7 +1497,6 @@ declare_lint_pass!(
NON_SHORTHAND_FIELD_PATTERNS,
UNSAFE_CODE,
MISSING_DOCS,
MISSING_COPY_IMPLEMENTATIONS,
MISSING_DEBUG_IMPLEMENTATIONS,
ANONYMOUS_PARAMETERS,
UNUSED_DOC_COMMENTS,
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,6 @@ late_lint_methods!(
NonUpperCaseGlobals: NonUpperCaseGlobals,
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
UnusedAllocation: UnusedAllocation,
// Depends on types used in type definitions
MissingCopyImplementations: MissingCopyImplementations,
// Depends on referenced function signatures in expressions
PtrNullChecks: PtrNullChecks,
MutableTransmutes: MutableTransmutes,
Expand Down Expand Up @@ -549,6 +547,11 @@ fn register_builtins(store: &mut LintStore) {
"converted into hard error, see RFC #3535 \
<https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
);
store.register_removed(
"missing_copy_implementations",
"it existed mostly for historical reasons, \
and not implementing `Copy` is common and reasonable",
);
}

fn register_internals(store: &mut LintStore) {
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,6 @@ pub struct BuiltinMissingDoc<'a> {
pub desc: &'a str,
}

#[derive(LintDiagnostic)]
#[diag(lint_builtin_missing_copy_impl)]
pub struct BuiltinMissingCopyImpl;

pub struct BuiltinMissingDebugImpl<'a> {
pub tcx: TyCtxt<'a>,
pub def_id: DefId,
Expand Down
2 changes: 0 additions & 2 deletions library/std/src/io/util.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(missing_copy_implementations)]

#[cfg(test)]
mod tests;

Expand Down
4 changes: 0 additions & 4 deletions src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[
description: r##"possible meta-variable misuse at macro definition"##,
},
Lint { label: "missing_abi", description: r##"No declared ABI for extern declaration"## },
Lint {
label: "missing_copy_implementations",
description: r##"detects potentially-forgotten implementations of `Copy`"##,
},
Lint {
label: "missing_debug_implementations",
description: r##"detects missing implementations of Debug"##,
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/lint/issue-111359.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#[deny(missing_debug_implementations)]
#[deny(missing_copy_implementations)]

mod priv_mod {
use std::convert::TryFrom;

pub struct BarPub;
//~^ ERROR type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
//~| ERROR type could implement `Copy`; consider adding `impl Copy`
struct BarPriv;

impl<'a> TryFrom<BarPriv> for u8 {
Expand Down
16 changes: 2 additions & 14 deletions tests/ui/lint/issue-111359.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
error: type could implement `Copy`; consider adding `impl Copy`
--> $DIR/issue-111359.rs:7:5
|
LL | pub struct BarPub;
| ^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/issue-111359.rs:2:8
|
LL | #[deny(missing_copy_implementations)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
--> $DIR/issue-111359.rs:7:5
--> $DIR/issue-111359.rs:6:5
|
LL | pub struct BarPub;
| ^^^^^^^^^^^^^^^^^^
Expand All @@ -22,5 +10,5 @@ note: the lint level is defined here
LL | #[deny(missing_debug_implementations)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

35 changes: 0 additions & 35 deletions tests/ui/lint/lint-missing-copy-implementations-allow.rs

This file was deleted.

15 changes: 0 additions & 15 deletions tests/ui/lint/lint-missing-copy-implementations.rs

This file was deleted.

16 changes: 0 additions & 16 deletions tests/ui/lint/lint-missing-copy-implementations.stderr

This file was deleted.

15 changes: 0 additions & 15 deletions tests/ui/lint/missing-copy-implementations-negative-copy.rs

This file was deleted.

Loading
Loading