mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
deprecate Eq::assert_receiver_is_total_eq and emit a FCW on manual impls
This commit is contained in:
@@ -26,15 +26,14 @@ pub(crate) fn expand_deriving_eq(
|
||||
additional_bounds: Vec::new(),
|
||||
supports_unions: true,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::assert_receiver_is_total_eq,
|
||||
name: sym::assert_fields_are_eq,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: true,
|
||||
nonself_args: vec![],
|
||||
ret_ty: Unit,
|
||||
attributes: thin_vec![
|
||||
cx.attr_word(sym::inline, span),
|
||||
cx.attr_nested_word(sym::doc, sym::hidden, span),
|
||||
cx.attr_nested_word(sym::coverage, sym::off, span)
|
||||
cx.attr_nested_word(sym::coverage, sym::off, span),
|
||||
],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
|
||||
@@ -24,12 +24,11 @@
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_errors::{Applicability, LintDiagnostic, msg};
|
||||
use rustc_feature::GateIssue;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::attrs::{AttributeKind, DocAttribute};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::FnKind as HirFnKind;
|
||||
use rustc_hir::{Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
|
||||
use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
@@ -59,7 +58,7 @@
|
||||
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
|
||||
BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub,
|
||||
BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
|
||||
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
|
||||
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel,
|
||||
};
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext};
|
||||
declare_lint! {
|
||||
@@ -3184,3 +3183,62 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `internal_eq_trait_method_impls` lint detects manual
|
||||
/// implementations of `Eq::assert_receiver_is_total_eq`.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #[derive(PartialEq)]
|
||||
/// pub struct Foo;
|
||||
///
|
||||
/// impl Eq for Foo {
|
||||
/// fn assert_receiver_is_total_eq(&self) {}
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// This method existed so that `#[derive(Eq)]` could check that all
|
||||
/// fields of a type implement `Eq`. Other users were never supposed
|
||||
/// to implement it and it was hidden from documentation.
|
||||
///
|
||||
/// Unfortunately, it was not explicitly marked as unstable and some
|
||||
/// people have now mistakenly assumed they had to implement this method.
|
||||
///
|
||||
/// As the method is never called by the standard library, you can safely
|
||||
/// remove any implementations of the method and just write `impl Eq for Foo {}`.
|
||||
///
|
||||
/// This is a [future-incompatible] lint to transition this to a hard
|
||||
/// error in the future. See [issue #152336] for more details.
|
||||
///
|
||||
/// [issue #152336]: https://github.com/rust-lang/rust/issues/152336
|
||||
pub INTERNAL_EQ_TRAIT_METHOD_IMPLS,
|
||||
Warn,
|
||||
"manual implementation of the internal `Eq::assert_receiver_is_total_eq` method",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: fcw!(FutureReleaseError #152336),
|
||||
report_in_deps: false,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass!(InternalEqTraitMethodImpls => [INTERNAL_EQ_TRAIT_METHOD_IMPLS]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for InternalEqTraitMethodImpls {
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::ImplItem<'tcx>) {
|
||||
if let ImplItemImplKind::Trait { defaultness: _, trait_item_def_id: Ok(trait_item_def_id) } =
|
||||
item.impl_kind
|
||||
&& cx.tcx.is_diagnostic_item(sym::assert_receiver_is_total_eq, trait_item_def_id)
|
||||
{
|
||||
cx.emit_span_lint(
|
||||
INTERNAL_EQ_TRAIT_METHOD_IMPLS,
|
||||
item.span,
|
||||
EqInternalMethodImplemented,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +250,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
FunctionCastsAsInteger: FunctionCastsAsInteger,
|
||||
CheckTransmutes: CheckTransmutes,
|
||||
LifetimeSyntax: LifetimeSyntax,
|
||||
InternalEqTraitMethodImpls: InternalEqTraitMethodImpls,
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
@@ -3926,3 +3926,8 @@ pub(crate) struct MalformedOnConstAttrLint {
|
||||
#[label("invalid option found here")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")]
|
||||
#[note("this method was used to add checks to the `Eq` derive macro")]
|
||||
pub(crate) struct EqInternalMethodImplemented;
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
assert,
|
||||
assert_eq,
|
||||
assert_eq_macro,
|
||||
assert_fields_are_eq,
|
||||
assert_inhabited,
|
||||
assert_macro,
|
||||
assert_mem_uninitialized_valid,
|
||||
@@ -1089,6 +1090,7 @@
|
||||
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
|
||||
integral,
|
||||
internal,
|
||||
internal_eq_trait_method_impls,
|
||||
internal_features,
|
||||
into_async_iter_into_iter,
|
||||
into_future,
|
||||
|
||||
+11
-3
@@ -336,16 +336,24 @@ fn ne(&self, other: &Rhs) -> bool {
|
||||
#[rustc_diagnostic_item = "Eq"]
|
||||
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
|
||||
pub const trait Eq: [const] PartialEq<Self> + PointeeSized {
|
||||
// this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
|
||||
// type implements `Eq` itself. The current deriving infrastructure means doing this assertion
|
||||
// without using a method on this trait is nearly impossible.
|
||||
// This method was used solely by `#[derive(Eq)]` to assert that every component of a
|
||||
// type implements `Eq` itself.
|
||||
//
|
||||
// This should never be implemented by hand.
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "assert_receiver_is_total_eq"]
|
||||
#[deprecated(since = "1.95.0", note = "implementation detail of `#[derive(Eq)]`")]
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
|
||||
// FIXME (#152504): this method is used solely by `#[derive(Eq)]` to assert that
|
||||
// every component of a type implements `Eq` itself. It will be removed again soon.
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
#[unstable(feature = "derive_eq_internals", issue = "none")]
|
||||
fn assert_fields_are_eq(&self) {}
|
||||
}
|
||||
|
||||
/// Derive macro generating an impl of the trait [`Eq`].
|
||||
|
||||
@@ -62,10 +62,9 @@ impl ::core::cmp::PartialEq for Empty {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Empty {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
fn assert_fields_are_eq(&self) {}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialOrd for Empty {
|
||||
@@ -139,10 +138,9 @@ impl ::core::cmp::PartialEq for Point {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Point {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
}
|
||||
}
|
||||
@@ -227,10 +225,9 @@ impl ::core::cmp::PartialEq for PackedPoint {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for PackedPoint {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
}
|
||||
}
|
||||
@@ -310,10 +307,9 @@ impl ::core::cmp::PartialEq for TupleSingleField {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for TupleSingleField {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
}
|
||||
}
|
||||
@@ -385,10 +381,9 @@ impl ::core::cmp::PartialEq for SingleField {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for SingleField {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<bool>;
|
||||
}
|
||||
}
|
||||
@@ -490,10 +485,9 @@ impl ::core::cmp::PartialEq for Big {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Big {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
}
|
||||
}
|
||||
@@ -754,10 +748,9 @@ impl ::core::cmp::PartialEq for Unsized {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Unsized {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<[u32]>;
|
||||
}
|
||||
}
|
||||
@@ -849,10 +842,9 @@ impl<T: ::core::cmp::PartialEq + Trait, U: ::core::cmp::PartialEq>
|
||||
#[automatically_derived]
|
||||
impl<T: ::core::cmp::Eq + Trait, U: ::core::cmp::Eq> ::core::cmp::Eq for
|
||||
Generic<T, U> where T::A: ::core::cmp::Eq {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<T>;
|
||||
let _: ::core::cmp::AssertParamIsEq<T::A>;
|
||||
let _: ::core::cmp::AssertParamIsEq<U>;
|
||||
@@ -971,10 +963,9 @@ impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
|
||||
impl<T: ::core::cmp::Eq + ::core::marker::Copy + Trait, U: ::core::cmp::Eq +
|
||||
::core::marker::Copy> ::core::cmp::Eq for PackedGeneric<T, U> where
|
||||
T::A: ::core::cmp::Eq + ::core::marker::Copy {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<T>;
|
||||
let _: ::core::cmp::AssertParamIsEq<T::A>;
|
||||
let _: ::core::cmp::AssertParamIsEq<U>;
|
||||
@@ -1056,10 +1047,9 @@ impl ::core::cmp::PartialEq for Enum0 {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Enum0 {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
fn assert_fields_are_eq(&self) {}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialOrd for Enum0 {
|
||||
@@ -1126,10 +1116,9 @@ impl ::core::cmp::PartialEq for Enum1 {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Enum1 {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
}
|
||||
}
|
||||
@@ -1192,10 +1181,9 @@ impl ::core::cmp::PartialEq for Fieldless1 {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Fieldless1 {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
fn assert_fields_are_eq(&self) {}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialOrd for Fieldless1 {
|
||||
@@ -1269,10 +1257,9 @@ impl ::core::cmp::PartialEq for Fieldless {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Fieldless {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
fn assert_fields_are_eq(&self) {}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialOrd for Fieldless {
|
||||
@@ -1379,10 +1366,9 @@ impl ::core::cmp::PartialEq for Mixed {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Mixed {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
let _: ::core::cmp::AssertParamIsEq<Option<u32>>;
|
||||
let _: ::core::cmp::AssertParamIsEq<Option<i32>>;
|
||||
@@ -1577,10 +1563,9 @@ impl ::core::cmp::PartialEq for Fielded {
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for Fielded {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
let _: ::core::cmp::AssertParamIsEq<bool>;
|
||||
let _: ::core::cmp::AssertParamIsEq<Option<i32>>;
|
||||
@@ -1699,10 +1684,9 @@ impl<T: ::core::cmp::PartialEq, U: ::core::cmp::PartialEq>
|
||||
#[automatically_derived]
|
||||
impl<T: ::core::cmp::Eq, U: ::core::cmp::Eq> ::core::cmp::Eq for
|
||||
EnumGeneric<T, U> {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) {
|
||||
fn assert_fields_are_eq(&self) {
|
||||
let _: ::core::cmp::AssertParamIsEq<T>;
|
||||
let _: ::core::cmp::AssertParamIsEq<U>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#![deny(deprecated, internal_eq_trait_method_impls)]
|
||||
pub struct Bad;
|
||||
|
||||
impl PartialEq for Bad {
|
||||
fn eq(&self, _: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Bad {
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
//~^ ERROR: `Eq::assert_receiver_is_total_eq` should never be implemented by hand [internal_eq_trait_method_impls]
|
||||
//~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct Good;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct Good2;
|
||||
|
||||
impl Eq for Good2 {}
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
pub trait SameName {
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
}
|
||||
|
||||
impl SameName for Foo {
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
Foo.assert_receiver_is_total_eq();
|
||||
Good2.assert_receiver_is_total_eq();
|
||||
//~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated]
|
||||
Good.assert_receiver_is_total_eq();
|
||||
//~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated]
|
||||
Bad.assert_receiver_is_total_eq();
|
||||
//~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated]
|
||||
}
|
||||
|
||||
#[forbid(internal_eq_trait_method_impls)]
|
||||
mod forbid {
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct Foo;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]`
|
||||
--> $DIR/internal_eq_trait_method_impls.rs:36:11
|
||||
|
|
||||
LL | Good2.assert_receiver_is_total_eq();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/internal_eq_trait_method_impls.rs:1:9
|
||||
|
|
||||
LL | #![deny(deprecated, internal_eq_trait_method_impls)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]`
|
||||
--> $DIR/internal_eq_trait_method_impls.rs:38:10
|
||||
|
|
||||
LL | Good.assert_receiver_is_total_eq();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]`
|
||||
--> $DIR/internal_eq_trait_method_impls.rs:40:9
|
||||
|
|
||||
LL | Bad.assert_receiver_is_total_eq();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `Eq::assert_receiver_is_total_eq` should never be implemented by hand
|
||||
--> $DIR/internal_eq_trait_method_impls.rs:11:5
|
||||
|
|
||||
LL | fn assert_receiver_is_total_eq(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #152336 <https://github.com/rust-lang/rust/issues/152336>
|
||||
= note: this method was used to add checks to the `Eq` derive macro
|
||||
note: the lint level is defined here
|
||||
--> $DIR/internal_eq_trait_method_impls.rs:1:21
|
||||
|
|
||||
LL | #![deny(deprecated, internal_eq_trait_method_impls)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
@@ -8,7 +8,7 @@ macro-stats #[derive(Hash)] 2 17 8.5
|
||||
macro-stats q! 1 26 26.0 519 519.0
|
||||
macro-stats #[derive(Ord)] 1 15 15.0 503 503.0
|
||||
macro-stats #[derive(Default)] 2 16 8.0 403 201.5
|
||||
macro-stats #[derive(Eq)] 1 11 11.0 319 319.0
|
||||
macro-stats #[derive(Eq)] 1 10 10.0 298 298.0
|
||||
macro-stats #[derive(Debug)] 1 8 8.0 277 277.0
|
||||
macro-stats #[derive(PartialEq)] 1 9 9.0 267 267.0
|
||||
macro-stats #[derive(Copy)] 1 2 2.0 61 61.0
|
||||
|
||||
Reference in New Issue
Block a user