Lifetime errors

Hello! I am trying to write library that can easely implement some design patterns.
It's shall work using iterators:

let mut cc = CommandChain::new();
cc.add_command(
	UserCommand::new()
);
cc.add_command(
	MailCommand::new()
);
for command in cc.iter() {
	cc.on_command("one1", &["Toto", "users"]);
	cc.on_command("one2", &["Toto", "users"]);
}
let t1 = thread::spawn(move||{
	for command in cc.iter() {
		cc.on_command("mutli1", &["Toto", "users"]);
	}
});
t1.join();

I wrote prototype for this code that is not working.
https://play.rust-lang.org/?gist=4dc3ece1145105b388b7&version=stable
I am thinking that my code may be valid.
Questions:

  1. Is there borrow checker problem or my code just invalid?
  2. It is possible to fix problem?
use std::thread;
//extern crate core;
trait Command {
	fn on_command(&self, name: &str, args: &[&str]);
}

struct CommandChain<'a> {
	commands: Vec<Box< Command + Send + Sized + 'a>>,
}
impl<'a> CommandChain<'a> {
	fn new() -> CommandChain<'a> {
		CommandChain{
			commands: Vec::new(),
		}
	}
	fn add_command<T:Command + Send + Sized + 'a>(&mut self, command: T) {
		self.commands.push(
			Box::new(
				command
			)
		);
	}
	fn run_command(&self, name: &str, args: &[&str]) {
		for command in self.commands.iter() {
			command.on_command(name, args);
		}
	}
	// fn iter(&self) -> core::slice::Iter<'a, Box<Command + Send + Sized + 'a>> {
	// 	return self.commands.iter();
	// }
}
impl <'a>Iterator for CommandChain<'a> {
	type Item = &'a Box<Command + Send + Sized>;
	fn next(&mut self) -> Option<Self::Item> {
		let value = self.commands.iter().next();
                                          //  ^ Error is here (elf.commands.iter()): error: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements [E0495]
		match value {
			Some(value) => {
				// let value: = Box::into_raw(*value);
				// let value: &Box<Command> = value;
				return Some(value);
			},
			None => {
				return None;
			},
		}
		// return self.commands.iter().next();
	}
}

struct UserCommand;
impl UserCommand {
	fn new() -> UserCommand {
		UserCommand
	}
}
impl Command for UserCommand {
	fn on_command(&self, name: &str, args: &[&str]) {
		println!("UserCommand handling '{}'.", name);
	}
}

struct MailCommand;
impl MailCommand {
	fn new() -> MailCommand {
		MailCommand
	}
}
impl Command for MailCommand {
	fn on_command(&self, name: &str, args: &[&str]) {
		println!("MailCommand handling '{}'", name);		
	}
}
fn main() {
	let mut cc = CommandChain::new();
	cc.add_command(
		UserCommand::new()
	);
	cc.add_command(
		MailCommand::new()
	);
	cc.run_command("one1", &["Toto", "users"]);
	cc.run_command("one2", &["Sender", "Subject"]);
	let t1 = thread::spawn(move||{
		// let cc = cc;
		cc.run_command("mutli1", &["Toto", "users"]);
	});
	// let t2 = thread::spawn(move||{
	// 	// let cc = cc;
	// 	cc.run_command("mutli2", &["Sender", "Subject"]);
	// });
	let threads = vec![t1];
	for thread in threads {
		thread.join();
	}
}
src/main.rs:35:29: 35:35 error: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements [E0495]
src/main.rs:35 		let value = self.commands.iter().next();
               		                          ^~~~~~
src/main.rs:34:2: 47:3 help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<Self::Item>
src/main.rs:34 	fn next(&mut self) -> Option<Self::Item> {
src/main.rs:35 		let value = self.commands.iter().next();
src/main.rs:36 		match value {
src/main.rs:37 			Some(value) => {
src/main.rs:38 				// let value: = Box::into_raw(*value);
src/main.rs:39 				// let value: &Box<Command> = value;
``

Your core problem is that the Iterator trait doesn't support yielding data which borrows the iterator: the compiler wants next to take &'a mut self because it needs to tie the lifetime 'a in type Item = &'a Box<...> to self somehow, but you don't have control over that because next is defined on the Iterator trait.

Ultimately, CommandChain cannot have its own Iterator impl; instead, you need a separate type implementing Iterator which can tie the lifetimes together correctly.

It looks like you were experimenting with having CommandChain::iter() return core::slice::Iter (std::slice::Iter would have been preferable, by the way), but you had some trouble with lifetimes there. If you don't mind the extra access slice::Iter provides, namely access to the underlying slice, you can make this work quite easily:

fn iter(&self) -> std::slice::Iter<Box<Command + Send + Sized + 'a>> {
    self.commands.iter()
}

All I did was take off the first 'a. Before, that was trying to tie the lifetime of the data in Iter to 'a, which is not what we wanted to do because 'a is required to outlive CommandChain<'a>. Now, it's allowing the compiler to infer the first lifetime of Iter from &self, so underneath, the definition looks something like this:

fn iter<'b>(&'b self) -> std::slice::Iter<'b, Box<Command + Send + Sized + 'a>>  {
    self.commands.iter()
}

So that Iter is correctly defined as borrowing &'b self: CommandChain<'a> for its lifetime 'b instead of for all of 'a. With this correction, your program compiles and runs successfully.

Edit 2: Removed first code block as it was breaking markdown for some reason and didn't contribute anything to the post.

2 Likes