diff options
author | Neal H. Walfield <neal@sequoia-pgp.org> | 2024-05-28 11:55:58 +0200 |
---|---|---|
committer | Neal H. Walfield <neal@sequoia-pgp.org> | 2024-05-28 15:15:50 +0200 |
commit | 4a3495a0edc0a82d9d3011ab9c7f51abc50e0983 (patch) | |
tree | 539024191b2af6de70609f9c0e3aad206a6982af /openpgp/src | |
parent | d55051425ec61a5d389878f8dd7f961de1c5c7f3 (diff) |
openpgp: Loosen the trait bounds on Key::clone and Key4::clone.
- Because we derive `Clone` for `Key` and `Key4`, `P` and `R` have
to implement `Clone`.
- This is not strictly necessary and we can drop this requirement by
implementing clone manually. Note: we already do this for
`KeyAmalgamation` for this exact reason.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/packet/key.rs | 25 | ||||
-rw-r--r-- | openpgp/src/packet/mod.rs | 19 |
2 files changed, 42 insertions, 2 deletions
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs index 112c2fa3..a0045f66 100644 --- a/openpgp/src/packet/key.rs +++ b/openpgp/src/packet/key.rs @@ -841,7 +841,6 @@ impl<P, R> Key<P, R> /// [Section 5.5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.5 /// [the documentation for `Key`]: super::Key /// [`Key`]: super::Key -#[derive(Clone)] pub struct Key4<P, R> where P: KeyParts, R: KeyRole { @@ -862,6 +861,30 @@ pub struct Key4<P, R> r: std::marker::PhantomData<R>, } +// derive(Clone) doesn't work as expected with generic type parameters +// that don't implement clone: it adds a trait bound on Clone to P and +// R in the Clone implementation. Happily, we don't need P or R to +// implement Clone: they are just marker traits, which we can clone +// manually. +// +// See: https://github.com/rust-lang/rust/issues/26925 +impl<P, R> Clone for Key4<P, R> + where P: KeyParts, R: KeyRole +{ + fn clone(&self) -> Self { + Key4 { + common: self.common.clone(), + creation_time: self.creation_time.clone(), + pk_algo: self.pk_algo.clone(), + mpis: self.mpis.clone(), + secret: self.secret.clone(), + fingerprint: self.fingerprint().clone().into(), + p: std::marker::PhantomData, + r: std::marker::PhantomData, + } + } +} + assert_send_and_sync!(Key4<P, R> where P: KeyParts, R: KeyRole); impl<P: KeyParts, R: KeyRole> PartialEq for Key4<P, R> { diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs index bbb8b1e4..a6e9182a 100644 --- a/openpgp/src/packet/mod.rs +++ b/openpgp/src/packet/mod.rs @@ -1541,13 +1541,30 @@ impl From<SKESK> for Packet { /// # } /// ``` #[non_exhaustive] -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +#[derive(PartialEq, Eq, Hash, Debug)] pub enum Key<P: key::KeyParts, R: key::KeyRole> { /// A version 4 `Key` packet. V4(Key4<P, R>), } assert_send_and_sync!(Key<P, R> where P: key::KeyParts, R: key::KeyRole); +// derive(Clone) doesn't work as expected with generic type parameters +// that don't implement clone: it adds a trait bound on Clone to P and +// R in the Clone implementation. Happily, we don't need P or R to +// implement Clone: they are just marker traits, which we can clone +// manually. +// +// See: https://github.com/rust-lang/rust/issues/26925 +impl<P, R> Clone for Key<P, R> + where P: key::KeyParts, R: key::KeyRole +{ + fn clone(&self) -> Self { + match self { + Key::V4(key) => Key::V4(key.clone()), + } + } +} + impl<P: key::KeyParts, R: key::KeyRole> fmt::Display for Key<P, R> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { |