Discourage use of base::Passed().
See discussion thread: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/8PJU6CEyGwg
No-Try: true
Bug: 812523
Change-Id: Ie021ad6803dbbaf02a4caba37c6b8a50a006b251
Reviewed-on: https://chromium-review.googlesource.com/919066
Commit-Queue: Max Morin <maxmorin@chromium.org>
Reviewed-by: Gabriel Charette <gab@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537637}
diff --git a/base/bind.h b/base/bind.h
index d1723b1e..b57a969c 100644
--- a/base/bind.h
+++ b/base/bind.h
@@ -364,13 +364,16 @@
// argument will CHECK() because the first invocation would have already
// transferred ownership to the target function.
//
+// Note that Passed() is not necessary with BindOnce(), as std::move() does the
+// same thing. Avoid Passed() in favor of std::move() with BindOnce().
+//
// EXAMPLE OF Passed():
//
// void TakesOwnership(std::unique_ptr<Foo> arg) { }
-// std::unique_ptr<Foo> CreateFoo() { return std::unique_ptr<Foo>(new Foo());
+// std::unique_ptr<Foo> CreateFoo() { return std::make_unique<Foo>();
// }
//
-// std::unique_ptr<Foo> f(new Foo());
+// auto f = std::make_unique<Foo>();
//
// // |cb| is given ownership of Foo(). |f| is now NULL.
// // You can use std::move(f) in place of &f, but it's more verbose.
@@ -388,11 +391,6 @@
// cb.Run(); // Foo() is now transferred to |arg| and deleted.
// cb.Run(); // This CHECK()s since Foo() already been used once.
//
-// Passed() is particularly useful with PostTask() when you are transferring
-// ownership of an argument into a task, but don't necessarily know if the
-// task will always be executed. This can happen if the task is cancellable
-// or if it is posted to a TaskRunner.
-//
// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and
// is best suited for use with the return value of a function or other temporary
// rvalues. The second takes a pointer to the scoper and is just syntactic sugar
diff --git a/docs/callback.md b/docs/callback.md
index f3f45f5..3c0d7ad 100644
--- a/docs/callback.md
+++ b/docs/callback.md
@@ -229,10 +229,10 @@
`const std::string&`. Like normal function dispatch, `base::Bind`, will coerce
parameter types if possible.
-### Avoiding Copies with Callback Parameters
+### Avoiding Copies With Callback Parameters
-A parameter of `base::Bind()` is moved into its internal storage if it is passed as a
-rvalue.
+A parameter of `base::BindRepeating()` or `base::BindOnce()` is moved into its
+internal storage if it is passed as a rvalue.
```cpp
std::vector<int> v = {1, 2, 3};
@@ -241,23 +241,37 @@
```
```cpp
-std::vector<int> v = {1, 2, 3};
// The vector is moved into the internal storage without copy.
base::Bind(&Foo, std::vector<int>({1, 2, 3}));
```
-A bound object is moved out to the target function if you use `base::Passed()`
-for the parameter. If you use `base::BindOnce()`, the bound object is moved out
-even without `base::Passed()`.
+Arguments bound with `base::BindOnce()` are always moved, if possible, to the
+target function.
+A function parameter that is passed by value and has a move constructor will be
+moved instead of copied.
+This makes it easy to use move-only types with `base::BindOnce()`.
+
+In contrast, arguments bound with `base::BindRepeating()` are only moved to the
+target function if the argument is bound with `base::Passed()`.
+
+**DANGER**:
+A `base::RepeatingCallback` can only be run once if arguments were bound with
+`base::Passed()`.
+For this reason, avoid `base::Passed()`.
+If you know a callback will only be called once, prefer to refactor code to
+work with `base::OnceCallback` instead.
+
+Avoid using `base::Passed()` with `base::BindOnce()`, as `std::move()` does the
+same thing and is more familiar.
```cpp
void Foo(std::unique_ptr<int>) {}
-std::unique_ptr<int> p(new int(42));
+auto p = std::make_unique<int>(42);
// |p| is moved into the internal storage of Bind(), and moved out to |Foo|.
base::BindOnce(&Foo, std::move(p));
-base::BindRepeating(&Foo, base::Passed(&p));
-base::BindRepeating(&Foo, base::Passed(std::move(p)));
+base::BindRepeating(&Foo, base::Passed(&p)); // Ok, but subtle.
+base::BindRepeating(&Foo, base::Passed(std::move(p))); // Ok, but subtle.
```
## Quick reference for advanced binding
@@ -337,10 +351,9 @@
```cpp
void TakesOwnership(std::unique_ptr<Foo> arg) {}
-std::unique_ptr<Foo> f(new Foo);
+auto f = std::make_unique<Foo>();
// f becomes null during the following call.
-base::RepeatingClosure cb =
- base::BindRepeating(&TakesOwnership, base::Passed(&f));
+base::OnceClosure cb = base::BindOnce(&TakesOwnership, std::move(f));
```
Ownership of the parameter will be with the callback until the callback is run,