Make lint missing-copy-implementations honor negative Copy impls

This commit is contained in:
León Orell Valerian Liehr 2023-07-30 13:33:26 +02:00
parent 8131b9774e
commit 2b8a3b44bf
No known key found for this signature in database
GPG Key ID: D17A07215F68E713
2 changed files with 38 additions and 0 deletions

View File

@ -62,6 +62,7 @@
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef};
use rustc_session::config::ExpectedValues;
@ -72,6 +73,7 @@
use rustc_span::{BytePos, InnerSpan, Span};
use rustc_target::abi::{Abi, FIRST_VARIANT};
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 crate::nonstandard_style::{method_context, MethodLateContext};
@ -710,6 +712,9 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
return;
}
if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) {
return;
}
// We shouldn't recommend implementing `Copy` on stateful things,
// such as iterators.
@ -745,6 +750,24 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
}
}
/// 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::ImplPolarity::Negative };
let obligation = traits::Obligation {
cause: traits::ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: ty::Binder::dummy(pred).to_predicate(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.

View File

@ -0,0 +1,15 @@
// Regression test for issue #101980.
// Ensure that we don't suggest impl'ing `Copy` for a type if it already impl's `!Copy`.
// check-pass
#![feature(negative_impls)]
#![deny(missing_copy_implementations)]
pub struct Struct {
pub field: i32,
}
impl !Copy for Struct {}
fn main() {}