why is there `move` needed, if both `answer`, and the arg of `Fn`, seem to be references (`&str`)? To a layman, this sounds like as if both "challenge" and "answer" should be borrowed - so why "move"? what's even to move here?
This is confusing, and Rust's error messages make it much worse. If you try to remove the `move`, you get an error:
> closure may outlive the current function, but it borrows `answer`, which is owned by the current function. To force the closure to take ownership of `answer` use the `move` keyword.
But 'answer' is of course not owned by the current function, and how can you take ownership through a shared reference?
The explanation is double indirection. By default, the closure captures a pointer to answer, which is itself a pointer on the stack. Without the 'move', inside the closure `answer` has type &&str and points into make_tester's stack frame. With the 'move', it copies the passed-in pointer. The error message is referring to the pointer itself, and this is not obvious.
Incidentally I have never found docs for the '+' syntax there, would appreciate a pointer to any.
> But 'answer' is of course not owned by the current function
As you imply later, ‘answer’ itself is owned by the current function, but the ‘answer’ value is a pointer that doesn’t own what it points to. This subtlety, that references are full values themselves, is definitely something to trip on, especially when double indirection starts popping up like this.
I believe what happens here is that the closure tries to capture it as a &&str. This is because it defaults to trying to take the environment by reference. The "move" in this case means that it will try to take it by value instead. This feels tricky semantically because references are types too, so "taking it by value" means taking a &T rather than a &&T, just like you may think about how taking a T is by value as opposed to &T.
In this closure you are moving `answer`, that is, you are moving the reference itself into scope. The `challenge` reference is already owned by the closure since it's a parameter. The move doesn't mean the closure owns the underlying strings, but the references themselves.