summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@sequoia-pgp.org>2024-05-28 11:55:58 +0200
committerNeal H. Walfield <neal@sequoia-pgp.org>2024-05-28 15:15:50 +0200
commit4a3495a0edc0a82d9d3011ab9c7f51abc50e0983 (patch)
tree539024191b2af6de70609f9c0e3aad206a6982af
parentd55051425ec61a5d389878f8dd7f961de1c5c7f3 (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.
-rw-r--r--openpgp/NEWS2
-rw-r--r--openpgp/src/packet/key.rs25
-rw-r--r--openpgp/src/packet/mod.rs19
3 files changed, 44 insertions, 2 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS
index 2721d65e..6d35c423 100644
--- a/openpgp/NEWS
+++ b/openpgp/NEWS
@@ -19,6 +19,8 @@
- The RustCrypto backend now supports ECDH and ECDSA over the NIST
curve P-521.
- CipherSuite::variants.
+** Notable fixes
+ - Loosen trait bounds on Key::clone and Key4::clone.
** Deprecated functionality
- ComponentBundle::certifications
- ComponentBundle::other_revocations
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 {