diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-12-12 11:37:20 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2024-01-25 11:19:44 +0100 |
commit | 50a8131156684353cb51f62c2ea5fa9d7be5c549 (patch) | |
tree | a966615876ba7609d995bec7d2c36b1d9e592944 | |
parent | 49b155e0e1b213d0379242903eeafc0599e3c4d8 (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.rs | 8 |
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) |