Skip to content

Commit fbc11e9

Browse files
committed
Auto merge of #114514 - matthiaskrgr:rollup-1rv4f3h, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - #114029 (Explain more clearly why `fn() -> T` can't be `#[derive(Clone)]`) - #114248 (Make lint missing-copy-implementations honor negative `Copy` impls) - #114498 (Print tidy command with bless tidy check failure) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 28b6607 + 9ad3be3 commit fbc11e9

File tree

4 files changed

+79
-1
lines changed

4 files changed

+79
-1
lines changed

Diff for: compiler/rustc_lint/src/builtin.rs

+23
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ use rustc_middle::lint::in_external_macro;
5858
use rustc_middle::ty::layout::LayoutOf;
5959
use rustc_middle::ty::print::with_no_trimmed_paths;
6060
use rustc_middle::ty::GenericArgKind;
61+
use rustc_middle::ty::ToPredicate;
6162
use rustc_middle::ty::TypeVisitableExt;
6263
use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
6364
use rustc_session::config::ExpectedValues;
@@ -68,6 +69,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
6869
use rustc_span::{BytePos, InnerSpan, Span};
6970
use rustc_target::abi::Abi;
7071
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
72+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
7173
use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
7274

7375
use crate::nonstandard_style::{method_context, MethodLateContext};
@@ -673,6 +675,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
673675
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
674676
return;
675677
}
678+
if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) {
679+
return;
680+
}
676681

677682
// We shouldn't recommend implementing `Copy` on stateful things,
678683
// such as iterators.
@@ -708,6 +713,24 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
708713
}
709714
}
710715

716+
/// Check whether a `ty` has a negative `Copy` implementation, ignoring outlives constraints.
717+
fn type_implements_negative_copy_modulo_regions<'tcx>(
718+
tcx: TyCtxt<'tcx>,
719+
ty: Ty<'tcx>,
720+
param_env: ty::ParamEnv<'tcx>,
721+
) -> bool {
722+
let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]);
723+
let pred = ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Negative };
724+
let obligation = traits::Obligation {
725+
cause: traits::ObligationCause::dummy(),
726+
param_env,
727+
recursion_depth: 0,
728+
predicate: ty::Binder::dummy(pred).to_predicate(tcx),
729+
};
730+
731+
tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
732+
}
733+
711734
declare_lint! {
712735
/// The `missing_debug_implementations` lint detects missing
713736
/// implementations of [`fmt::Debug`] for public types.

Diff for: library/core/src/clone.rs

+40
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,46 @@
8686
/// }
8787
/// ```
8888
///
89+
/// If we `derive`:
90+
///
91+
/// ```
92+
/// #[derive(Copy, Clone)]
93+
/// struct Generate<T>(fn() -> T);
94+
/// ```
95+
///
96+
/// the auto-derived implementations will have unnecessary `T: Copy` and `T: Clone` bounds:
97+
///
98+
/// ```
99+
/// # struct Generate<T>(fn() -> T);
100+
///
101+
/// // Automatically derived
102+
/// impl<T: Copy> Copy for Generate<T> { }
103+
///
104+
/// // Automatically derived
105+
/// impl<T: Clone> Clone for Generate<T> {
106+
/// fn clone(&self) -> Generate<T> {
107+
/// Generate(Clone::clone(&self.0))
108+
/// }
109+
/// }
110+
/// ```
111+
///
112+
/// The bounds are unnecessary because clearly the function itself should be
113+
/// copy- and cloneable even if its return type is not:
114+
///
115+
/// ```compile_fail,E0599
116+
/// #[derive(Copy, Clone)]
117+
/// struct Generate<T>(fn() -> T);
118+
///
119+
/// struct NotCloneable;
120+
///
121+
/// fn generate_not_cloneable() -> NotCloneable {
122+
/// NotCloneable
123+
/// }
124+
///
125+
/// Generate(generate_not_cloneable).clone(); // error: trait bounds were not satisfied
126+
/// // Note: With the manual implementations the above line will compile.
127+
/// ```
128+
///
89129
/// ## Additional implementors
90130
///
91131
/// In addition to the [implementors listed below][impls],

Diff for: src/tools/tidy/src/fluent_alphabetical.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) {
2323
tidy_error!(
2424
bad,
2525
"{filename}: message `{}` appears before `{}`, but is alphabetically later than it
26-
run tidy with `--bless` to sort the file correctly",
26+
run `./x.py test tidy --bless` to sort the file correctly",
2727
name.as_str(),
2828
next.as_str()
2929
);
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)