Not at all! This discussion has been very helpful to me to clarify my thinking around these issues. I understand now why the compiler is raising the error though I do agree that the error message could be more helpful. The error message and detailed explanation for the error E0502 eventually lead me to the section on &mut references in the book. I thought the example given there exactly matched my use case. I did not even consider that the method signature of the batch_process
method might be relevant in determining the lifetime of the &mut batch
reference in main()
.
You are getting at the heart of the problem here: I do not fully understand why (or rather if) the 'b: 'a
constraint is even required. I arrived at it more through trial and error than through careful consideration but haven't found a way to remove it. Unfortunately, in the playground example I posted at Rust Playground it is not actually required. But in my real code it is and I am not sure of the reason. The actual version of the batch_process function can be found here: https://github.com/aerospike/aerospike-client-rust/blob/batch-reads/src/batch/batch_executor.rs#L46. If I change that method signature from
pub fn execute_batch_read<'a, 'b: 'a>(&self,
policy: &BatchPolicy,
batch_reads: &'b mut [BatchRead<'a>])
-> Result<()>
to simply
pub fn execute_batch_read<'a, 'b>(&self,
policy: &BatchPolicy,
batch_reads: &'b mut [BatchRead<'a>])
-> Result<()>
then I get the following compile error which I do not understand:
Compiling aerospike v0.0.1 (file:///Users/jhecking/aerospike/aerospike-client-rust)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
--> src/client.rs:196:18
|
196 | executor.execute_batch_read(policy, batch_reads)
| ^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the body at 194:47...
--> src/client.rs:194:48
|
194 | -> Result<()> {
| ________________________________________________^ starting here...
195 | | let executor = BatchExecutor::new(self.cluster.clone(), self.thread_pool.clone());
196 | | executor.execute_batch_read(policy, batch_reads)
197 | | }
| |_____^ ...ending here
note: ...so that reference does not outlive borrowed content
--> src/client.rs:196:45
|
196 | executor.execute_batch_read(policy, batch_reads)
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 194:47...
--> src/client.rs:194:48
|
194 | -> Result<()> {
| ________________________________________________^ starting here...
195 | | let executor = BatchExecutor::new(self.cluster.clone(), self.thread_pool.clone());
196 | | executor.execute_batch_read(policy, batch_reads)
197 | | }
| |_____^ ...ending here
note: ...so that expression is assignable (expected &mut [batch::batch_read::BatchRead<'_>], found &mut [batch::batch_read::BatchRead<'b>])
--> src/client.rs:196:45
|
196 | executor.execute_batch_read(policy, batch_reads)
| ^^^^^^^^^^^
error: aborting due to previous error
If I remove the lifetime declaration 'b
entirely I am getting this somewhat similar and to me equally cryptical error:
Compiling aerospike v0.0.1 (file:///Users/jhecking/aerospike/aerospike-client-rust)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/batch/batch_executor.rs:51:27
|
51 | let batch_reads = SharedSlice::new(batch_reads);
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the body at 49:48...
--> src/batch/batch_executor.rs:49:49
|
49 | -> Result<()> {
| ^
note: ...so that reference does not outlive borrowed content
--> src/batch/batch_executor.rs:51:44
|
51 | let batch_reads = SharedSlice::new(batch_reads);
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 49:48...
--> src/batch/batch_executor.rs:49:49
|
49 | -> Result<()> {
| ^
note: ...so that expression is assignable (expected batch::batch_executor::SharedSlice<'_, batch::batch_read::BatchRead<'_>>, found batch::batch_executor::SharedSlice<'_, batch::batch_read::BatchRead<'a>>)
--> src/batch/batch_executor.rs:51:27
|
51 | let batch_reads = SharedSlice::new(batch_reads);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
In the simplified batch_process
method I can remove the 'b
lifetime entirely and the code still compiles.