Skip to content

Commit 2b8a3b4

Browse files
committed
Make lint missing-copy-implementations honor negative Copy impls
1 parent 8131b97 commit 2b8a3b4

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

compiler/rustc_lint/src/builtin.rs

+23
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ use rustc_middle::lint::in_external_macro;
6262
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
6363
use rustc_middle::ty::print::with_no_trimmed_paths;
6464
use rustc_middle::ty::GenericArgKind;
65+
use rustc_middle::ty::ToPredicate;
6566
use rustc_middle::ty::TypeVisitableExt;
6667
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef};
6768
use rustc_session::config::ExpectedValues;
@@ -72,6 +73,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
7273
use rustc_span::{BytePos, InnerSpan, Span};
7374
use rustc_target::abi::{Abi, FIRST_VARIANT};
7475
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
76+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
7577
use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
7678

7779
use crate::nonstandard_style::{method_context, MethodLateContext};
@@ -710,6 +712,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
710712
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
711713
return;
712714
}
715+
if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) {
716+
return;
717+
}
713718

714719
// We shouldn't recommend implementing `Copy` on stateful things,
715720
// such as iterators.
@@ -745,6 +750,24 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
745750
}
746751
}
747752

753+
/// Check whether a `ty` has a negative `Copy` implementation, ignoring outlives constraints.
754+
fn type_implements_negative_copy_modulo_regions<'tcx>(
755+
tcx: TyCtxt<'tcx>,
756+
ty: Ty<'tcx>,
757+
param_env: ty::ParamEnv<'tcx>,
758+
) -> bool {
759+
let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]);
760+
let pred = ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Negative };
761+
let obligation = traits::Obligation {
762+
cause: traits::ObligationCause::dummy(),
763+
param_env,
764+
recursion_depth: 0,
765+
predicate: ty::Binder::dummy(pred).to_predicate(tcx),
766+
};
767+
768+
tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
769+
}
770+
748771
declare_lint! {
749772
/// The `missing_debug_implementations` lint detects missing
750773
/// implementations of [`fmt::Debug`] for public types.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Regression test for issue #101980.
2+
// Ensure that we don't suggest impl'ing `Copy` for a type if it already impl's `!Copy`.
3+
4+
// check-pass
5+
6+
#![feature(negative_impls)]
7+
#![deny(missing_copy_implementations)]
8+
9+
pub struct Struct {
10+
pub field: i32,
11+
}
12+
13+
impl !Copy for Struct {}
14+
15+
fn main() {}

0 commit comments

Comments
 (0)