Skip to content

Commit faf29de

Browse files
committed
deprecate Eq::assert_receiver_is_total_eq and emit a FCW on manual implementations
1 parent 3391c01 commit faf29de

File tree

7 files changed

+125
-3
lines changed

7 files changed

+125
-3
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ lint_enum_intrinsics_mem_variant =
318318
the return value of `mem::variant_count` is unspecified when called with a non-enum type
319319
.note = the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum
320320
321+
lint_eq_internal_method = `Eq::assert_receiver_is_total_eq` should never be implemented by hand
322+
.note = this method is only used to add checks to the `Eq` derive macro
323+
321324
lint_expectation = this lint expectation is unfulfilled
322325
.note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
323326
.rationale = {$rationale}

compiler/rustc_lint/src/builtin.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@ use rustc_ast_pretty::pprust::expr_to_string;
2424
use rustc_attr_parsing::AttributeParser;
2525
use rustc_errors::{Applicability, LintDiagnostic};
2626
use rustc_feature::GateIssue;
27-
use rustc_hir as hir;
2827
use rustc_hir::attrs::{AttributeKind, DocAttribute};
2928
use rustc_hir::def::{DefKind, Res};
3029
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
3130
use rustc_hir::intravisit::FnKind as HirFnKind;
32-
use rustc_hir::{Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
31+
use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
3332
use rustc_middle::bug;
3433
use rustc_middle::lint::LevelAndSource;
3534
use rustc_middle::ty::layout::LayoutOf;
@@ -59,7 +58,7 @@ use crate::lints::{
5958
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
6059
BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub,
6160
BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
62-
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
61+
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel,
6362
};
6463
use crate::{
6564
EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
@@ -3191,3 +3190,32 @@ impl EarlyLintPass for SpecialModuleName {
31913190
}
31923191
}
31933192
}
3193+
3194+
declare_lint! {
3195+
pub EQ_ASSERT_RECEIVER_IS_TOTAL_EQ_IMPL,
3196+
Warn,
3197+
"manual implementation of the internal `Eq::assert_receiver_is_total_eq` method",
3198+
@future_incompatible = FutureIncompatibleInfo {
3199+
reason: fcw!(FutureReleaseError #150000),
3200+
report_in_deps: false,
3201+
};
3202+
}
3203+
3204+
declare_lint_pass!(EqAssertReceiverIsTotalEq => [EQ_ASSERT_RECEIVER_IS_TOTAL_EQ_IMPL]);
3205+
3206+
impl<'tcx> LateLintPass<'tcx> for EqAssertReceiverIsTotalEq {
3207+
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::ImplItem<'tcx>) {
3208+
if let ImplItemImplKind::Trait { defaultness: _, trait_item_def_id: Ok(trait_item_def_id) } =
3209+
item.impl_kind
3210+
&& item.ident.name == sym::assert_receiver_is_total_eq
3211+
&& cx.tcx.is_diagnostic_item(sym::assert_receiver_is_total_eq, trait_item_def_id)
3212+
&& !item.span.from_expansion()
3213+
{
3214+
cx.emit_span_lint(
3215+
EQ_ASSERT_RECEIVER_IS_TOTAL_EQ_IMPL,
3216+
item.span,
3217+
EqInternalMethodImplemented,
3218+
);
3219+
}
3220+
}
3221+
}

compiler/rustc_lint/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ late_lint_methods!(
249249
FunctionCastsAsInteger: FunctionCastsAsInteger,
250250
CheckTransmutes: CheckTransmutes,
251251
LifetimeSyntax: LifetimeSyntax,
252+
EqAssertReceiverIsTotalEq: EqAssertReceiverIsTotalEq,
252253
]
253254
]
254255
);

compiler/rustc_lint/src/lints.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3298,3 +3298,8 @@ pub(crate) struct DocTestUnknown {
32983298
#[derive(LintDiagnostic)]
32993299
#[diag(lint_doc_test_literal)]
33003300
pub(crate) struct DocTestLiteral;
3301+
3302+
#[derive(LintDiagnostic)]
3303+
#[diag(lint_eq_internal_method)]
3304+
#[note]
3305+
pub(crate) struct EqInternalMethodImplemented;

library/core/src/cmp.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ pub const trait Eq: [const] PartialEq<Self> + PointeeSized {
345345
#[coverage(off)]
346346
#[inline]
347347
#[stable(feature = "rust1", since = "1.0.0")]
348+
#[rustc_diagnostic_item = "assert_receiver_is_total_eq"]
349+
#[deprecated(since = "1.94.0", note = "implementation detail of `#[derive(Eq)]`")]
348350
fn assert_receiver_is_total_eq(&self) {}
349351
}
350352

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#![deny(deprecated, eq_assert_receiver_is_total_eq_impl)]
2+
pub struct Bad;
3+
4+
impl PartialEq for Bad {
5+
fn eq(&self, _: &Self) -> bool {
6+
true
7+
}
8+
}
9+
10+
impl Eq for Bad {
11+
fn assert_receiver_is_total_eq(&self) {}
12+
//~^ ERROR: `Eq::assert_receiver_is_total_eq` should never be implemented by hand [eq_assert_receiver_is_total_eq_impl]
13+
//~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
14+
}
15+
16+
#[derive(PartialEq, Eq)]
17+
pub struct Good;
18+
19+
#[derive(PartialEq)]
20+
pub struct Good2;
21+
22+
impl Eq for Good2 {}
23+
24+
pub struct Foo;
25+
26+
pub trait SameName {
27+
fn assert_receiver_is_total_eq(&self) {}
28+
}
29+
30+
impl SameName for Foo {
31+
fn assert_receiver_is_total_eq(&self) {}
32+
}
33+
34+
pub fn main() {
35+
Foo.assert_receiver_is_total_eq();
36+
Good2.assert_receiver_is_total_eq();
37+
//~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated]
38+
Good.assert_receiver_is_total_eq();
39+
//~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated]
40+
Bad.assert_receiver_is_total_eq();
41+
//~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated]
42+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]`
2+
--> $DIR/eq_assert_receiver_is_total_eq_impl.rs:36:11
3+
|
4+
LL | Good2.assert_receiver_is_total_eq();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/eq_assert_receiver_is_total_eq_impl.rs:1:9
9+
|
10+
LL | #![deny(deprecated, eq_assert_receiver_is_total_eq_impl)]
11+
| ^^^^^^^^^^
12+
13+
error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]`
14+
--> $DIR/eq_assert_receiver_is_total_eq_impl.rs:38:10
15+
|
16+
LL | Good.assert_receiver_is_total_eq();
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]`
20+
--> $DIR/eq_assert_receiver_is_total_eq_impl.rs:40:9
21+
|
22+
LL | Bad.assert_receiver_is_total_eq();
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: `Eq::assert_receiver_is_total_eq` should never be implemented by hand
26+
--> $DIR/eq_assert_receiver_is_total_eq_impl.rs:11:5
27+
|
28+
LL | fn assert_receiver_is_total_eq(&self) {}
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
|
31+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
32+
= note: for more information, see issue #150000 <https://github.com/rust-lang/rust/issues/150000>
33+
= note: this method is only used to add checks to the `Eq` derive macro
34+
note: the lint level is defined here
35+
--> $DIR/eq_assert_receiver_is_total_eq_impl.rs:1:21
36+
|
37+
LL | #![deny(deprecated, eq_assert_receiver_is_total_eq_impl)]
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
40+
error: aborting due to 4 previous errors
41+

0 commit comments

Comments
 (0)