summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-12-12 11:37:20 +0100
committerJustus Winter <justus@sequoia-pgp.org>2024-01-25 11:19:44 +0100
commit50a8131156684353cb51f62c2ea5fa9d7be5c549 (patch)
treea966615876ba7609d995bec7d2c36b1d9e592944
parent49b155e0e1b213d0379242903eeafc0599e3c4d8 (diff)
openpgp: Tweak lifetime of filter function's argument.
- Previously, the filter operated on references with the lifetime 'a only, which is the lifetime associated with the Cert the TSK object references. Change the signature to take a reference with an anonymous lifetime instead. - This makes the filter more general, but it can no longer rely on the fact that the references are live for 'a. However, the function is a Fn, not a FnMut, and returns a bool, so the function cannot store the reference anywhere, so this shouldn't make a difference in practice. - Annoyingly, there is a wrinkle. If a closure bound to an identifier is given to TSK::set_filter, the Rust compiler incorrectly (or over eagerly?) specializes the function in a way that it doesn't match the callback's prototype: error[E0308]: mismatched types --> openpgp/src/serialize/cert.rs:946:16 | 946 | check!(tsk_0.as_tsk().set_filter(no_secrets), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected trait `for<'a> Fn<(&'a packet::Key<packet::key::SecretParts, packet::key::UnspecifiedRole>,)>` found trait `Fn<(&packet::Key<packet::key::SecretParts, packet::key::UnspecifiedRole>,)>` note: this closure does not fulfill the lifetime requirements --> openpgp/src/serialize/cert.rs:940:26 | 940 | let no_secrets = |_| false; | ^^^ note: the lifetime requirement is introduced here --> openpgp/src/serialize/cert.rs:318:23 | 318 | where P: 'a + Fn(&key::UnspecifiedSecret) -> bool | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `FnOnce` is not general enough --> openpgp/src/serialize/cert.rs:946:16 | 946 | check!(tsk_0.as_tsk().set_filter(no_secrets), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | = note: closure with signature `fn(&'2 packet::Key<packet::key::SecretParts, packet::key::UnspecifiedRole>) -> bool` must implement `FnOnce<(&'1 packet::Key<packet::key::SecretParts, packet::key::UnspecifiedRole>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 packet::Key<packet::key::SecretParts, packet::key::UnspecifiedRole>,)>`, for some specific lifetime `'2` This is easily fixed by providing a partial type for the callback's argument. This commit includes a tweak for our test.
-rw-r--r--openpgp/src/serialize/cert.rs8
1 files changed, 4 insertions, 4 deletions
diff --git a/openpgp/src/serialize/cert.rs b/openpgp/src/serialize/cert.rs
index 4d98569a..83e804ed 100644
--- a/openpgp/src/serialize/cert.rs
+++ b/openpgp/src/serialize/cert.rs
@@ -294,7 +294,7 @@ impl Cert {
/// ```
pub struct TSK<'a> {
pub(crate) cert: &'a Cert,
- filter: Box<dyn Fn(&'a key::UnspecifiedSecret) -> bool + 'a>,
+ filter: Box<dyn Fn(&key::UnspecifiedSecret) -> bool + 'a>,
emit_stubs: bool,
}
@@ -385,7 +385,7 @@ impl<'a> TSK<'a> {
/// # Ok(()) }
/// ```
pub fn set_filter<P>(mut self, predicate: P) -> Self
- where P: 'a + Fn(&'a key::UnspecifiedSecret) -> bool
+ where P: 'a + Fn(&key::UnspecifiedSecret) -> bool
{
self.filter = Box::new(predicate);
self
@@ -1029,7 +1029,7 @@ mod test {
check!(&cert_0, &tsk_0, true);
// Filters out secrets.
- let no_secrets = |_| false;
+ let no_secrets = |_: &_| false;
// TSK's equality.
check!(tsk_0.as_tsk(), tsk_1.as_tsk(), true);
@@ -1070,7 +1070,7 @@ mod test {
let tsk = Cert::from_bytes(crate::tests::key("testy-private.pgp"))?;
// Filters out secrets.
- let no_secrets = |_| false;
+ let no_secrets = |_: &_| false;
assert!(! cert.as_tsk().emits_secret_key_packets());
assert!(cert.as_tsk().emit_secret_key_stubs(true)