From 9f1f7119bac9f4cfbbcba084ec4a95bd2cadd733 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 9 Jul 2024 09:44:14 -0700 Subject: [PATCH] der-derive: avoid type inference when using default This is another take on #1441. This is intended to make sure we can still continue to use `Default::default` and not break future releases by mistake. --- der/derive/src/sequence/field.rs | 15 +++++---- der/tests/derive.rs | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/der/derive/src/sequence/field.rs b/der/derive/src/sequence/field.rs index 3fb183208..d91599c0a 100644 --- a/der/derive/src/sequence/field.rs +++ b/der/derive/src/sequence/field.rs @@ -97,7 +97,7 @@ impl SequenceField { !attrs.optional, "`default`, and `optional` are mutually exclusive" ); - lowerer.apply_default(&self.ident, default); + lowerer.apply_default(&self.ident, default, &self.field_type); } lowerer.into_tokens() @@ -189,14 +189,17 @@ impl LowerFieldEncoder { } /// Handle default value for a type. - fn apply_default(&mut self, ident: &Ident, default: &Path) { + fn apply_default(&mut self, ident: &Ident, default: &Path, field_type: &Type) { let encoder = &self.encoder; self.encoder = quote! { - if &self.#ident == &#default() { - None - } else { - Some(#encoder) + { + let default_value: #field_type = #default(); + if &self.#ident == &default_value { + None + } else { + Some(#encoder) + } } }; } diff --git a/der/tests/derive.rs b/der/tests/derive.rs index b0ae37910..fa2e1c7e9 100644 --- a/der/tests/derive.rs +++ b/der/tests/derive.rs @@ -461,3 +461,59 @@ mod sequence { ); } } + +mod infer_default { + //! When another crate might define a PartialEq for another type, the use of + //! `default="Default::default"` in the der derivation will not provide enough + //! information for `der_derive` crate to figure out. + //! + //! This provides a reproduction for that case. This is intended to fail when we + //! compile tests. + //! ``` + //! error[E0282]: type annotations needed + //! --> der/tests/derive.rs:480:26 + //! | + //!480 | #[asn1(default = "Default::default")] + //! | ^^^^^^^^^^^^^^^^^^ cannot infer type + //! + //!error[E0283]: type annotations needed + //! --> der/tests/derive.rs:478:14 + //! | + //!478 | #[derive(Sequence)] + //! | ^^^^^^^^ cannot infer type + //! | + //!note: multiple `impl`s satisfying `bool: PartialEq<_>` found + //! --> der/tests/derive.rs:472:5 + //! | + //!472 | impl PartialEq for bool { + //! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + //! = note: and another `impl` found in the `core` crate: + //! - impl PartialEq for bool + //! where the constant `host` has type `bool`; + //! = note: required for `&bool` to implement `PartialEq<&_>` + //! = note: this error originates in the derive macro `Sequence` (in Nightly builds, run with -Z macro-backtrace for more info) + //! ``` + + use der::Sequence; + + struct BooleanIsh; + + impl PartialEq for bool { + fn eq(&self, _other: &BooleanIsh) -> bool { + unimplemented!("This is only here to mess up the compiler's type inference") + } + } + + #[derive(Sequence)] + struct Foo { + #[asn1(default = "Default::default")] + pub use_default_default: bool, + + #[asn1(default = "something_true")] + pub use_custom: bool, + } + + fn something_true() -> bool { + todo!() + } +}