Change the behavior of JoinHandle
diff --git a/src/join_handle.rs b/src/join_handle.rs
index 487adf5..745c786 100644
--- a/src/join_handle.rs
+++ b/src/join_handle.rs
@@ -1,6 +1,7 @@
 use core::fmt;
 use core::future::Future;
 use core::marker::{PhantomData, Unpin};
+use core::mem;
 use core::pin::Pin;
 use core::ptr::NonNull;
 use core::sync::atomic::Ordering;
@@ -29,130 +30,131 @@
 impl<R> Unpin for JoinHandle<R> {}
 
 impl<R> JoinHandle<R> {
-    /// Cancels the task.
-    ///
-    /// If the task has already completed, calling this method will have no effect.
-    ///
-    /// When a task is canceled, its future will not be polled again.
-    pub fn cancel(&self) {
+    pub fn detach(self) {
         let ptr = self.raw_task.as_ptr();
+        mem::forget(self);
+        unsafe {
+            Self::drop_raw(ptr);
+        }
+    }
+
+    pub async fn cancel(self) -> Option<R> {
+        unsafe {
+            Self::cancel_raw(self.raw_task.as_ptr());
+        }
+        self.await
+    }
+
+    unsafe fn cancel_raw(ptr: *const ()) {
         let header = ptr as *const Header;
 
-        unsafe {
-            let mut state = (*header).state.load(Ordering::Acquire);
+        let mut state = (*header).state.load(Ordering::Acquire);
 
-            loop {
-                // If the task has been completed or closed, it can't be canceled.
-                if state & (COMPLETED | CLOSED) != 0 {
+        loop {
+            // If the task has been completed or closed, it can't be canceled.
+            if state & (COMPLETED | CLOSED) != 0 {
+                break;
+            }
+
+            // If the task is not scheduled nor running, we'll need to schedule it.
+            let new = if state & (SCHEDULED | RUNNING) == 0 {
+                (state | SCHEDULED | CLOSED) + REFERENCE
+            } else {
+                state | CLOSED
+            };
+
+            // Mark the task as closed.
+            match (*header).state.compare_exchange_weak(
+                state,
+                new,
+                Ordering::AcqRel,
+                Ordering::Acquire,
+            ) {
+                Ok(_) => {
+                    // If the task is not scheduled nor running, schedule it one more time so
+                    // that its future gets dropped by the executor.
+                    if state & (SCHEDULED | RUNNING) == 0 {
+                        ((*header).vtable.schedule)(ptr);
+                    }
+
+                    // Notify the awaiter that the task has been closed.
+                    if state & AWAITER != 0 {
+                        (*header).notify(None);
+                    }
+
                     break;
                 }
-
-                // If the task is not scheduled nor running, we'll need to schedule it.
-                let new = if state & (SCHEDULED | RUNNING) == 0 {
-                    (state | SCHEDULED | CLOSED) + REFERENCE
-                } else {
-                    state | CLOSED
-                };
-
-                // Mark the task as closed.
-                match (*header).state.compare_exchange_weak(
-                    state,
-                    new,
-                    Ordering::AcqRel,
-                    Ordering::Acquire,
-                ) {
-                    Ok(_) => {
-                        // If the task is not scheduled nor running, schedule it one more time so
-                        // that its future gets dropped by the executor.
-                        if state & (SCHEDULED | RUNNING) == 0 {
-                            ((*header).vtable.schedule)(ptr);
-                        }
-
-                        // Notify the awaiter that the task has been closed.
-                        if state & AWAITER != 0 {
-                            (*header).notify(None);
-                        }
-
-                        break;
-                    }
-                    Err(s) => state = s,
-                }
+                Err(s) => state = s,
             }
         }
     }
-}
 
-impl<R> Drop for JoinHandle<R> {
-    fn drop(&mut self) {
-        let ptr = self.raw_task.as_ptr();
+    unsafe fn drop_raw(ptr: *const ()) {
         let header = ptr as *const Header;
 
         // A place where the output will be stored in case it needs to be dropped.
         let mut output = None;
 
-        unsafe {
-            // Optimistically assume the `JoinHandle` is being dropped just after creating the
-            // task. This is a common case so if the handle is not used, the overhead of it is only
-            // one compare-exchange operation.
-            if let Err(mut state) = (*header).state.compare_exchange_weak(
-                SCHEDULED | HANDLE | REFERENCE,
-                SCHEDULED | REFERENCE,
-                Ordering::AcqRel,
-                Ordering::Acquire,
-            ) {
-                loop {
-                    // If the task has been completed but not yet closed, that means its output
-                    // must be dropped.
-                    if state & COMPLETED != 0 && state & CLOSED == 0 {
-                        // Mark the task as closed in order to grab its output.
-                        match (*header).state.compare_exchange_weak(
-                            state,
-                            state | CLOSED,
-                            Ordering::AcqRel,
-                            Ordering::Acquire,
-                        ) {
-                            Ok(_) => {
-                                // Read the output.
-                                output =
-                                    Some((((*header).vtable.get_output)(ptr) as *mut R).read());
+        // Optimistically assume the `JoinHandle` is being detached just after creating the
+        // task. This is a common case so if the handle is not used, the overhead of it is only
+        // one compare-exchange operation.
+        if let Err(mut state) = (*header).state.compare_exchange_weak(
+            SCHEDULED | HANDLE | REFERENCE,
+            SCHEDULED | REFERENCE,
+            Ordering::AcqRel,
+            Ordering::Acquire,
+        ) {
+            loop {
+                // If the task has been completed but not yet closed, that means its output
+                // must be dropped.
+                if state & COMPLETED != 0 && state & CLOSED == 0 {
+                    // Mark the task as closed in order to grab its output.
+                    match (*header).state.compare_exchange_weak(
+                        state,
+                        state | CLOSED,
+                        Ordering::AcqRel,
+                        Ordering::Acquire,
+                    ) {
+                        Ok(_) => {
+                            // Read the output.
+                            output = Some((((*header).vtable.get_output)(ptr) as *mut R).read());
 
-                                // Update the state variable because we're continuing the loop.
-                                state |= CLOSED;
-                            }
-                            Err(s) => state = s,
+                            // Update the state variable because we're continuing the loop.
+                            state |= CLOSED;
                         }
+                        Err(s) => state = s,
+                    }
+                } else {
+                    // If this is the last reference to the task and it's not closed, then
+                    // close it and schedule one more time so that its future gets dropped by
+                    // the executor.
+                    let new = if state & (!(REFERENCE - 1) | CLOSED) == 0 {
+                        SCHEDULED | CLOSED | REFERENCE
                     } else {
-                        // If this is the last reference to the task and it's not closed, then
-                        // close it and schedule one more time so that its future gets dropped by
-                        // the executor.
-                        let new = if state & (!(REFERENCE - 1) | CLOSED) == 0 {
-                            SCHEDULED | CLOSED | REFERENCE
-                        } else {
-                            state & !HANDLE
-                        };
+                        state & !HANDLE
+                    };
 
-                        // Unset the handle flag.
-                        match (*header).state.compare_exchange_weak(
-                            state,
-                            new,
-                            Ordering::AcqRel,
-                            Ordering::Acquire,
-                        ) {
-                            Ok(_) => {
-                                // If this is the last reference to the task, we need to either
-                                // schedule dropping its future or destroy it.
-                                if state & !(REFERENCE - 1) == 0 {
-                                    if state & CLOSED == 0 {
-                                        ((*header).vtable.schedule)(ptr);
-                                    } else {
-                                        ((*header).vtable.destroy)(ptr);
-                                    }
+                    // Unset the handle flag.
+                    match (*header).state.compare_exchange_weak(
+                        state,
+                        new,
+                        Ordering::AcqRel,
+                        Ordering::Acquire,
+                    ) {
+                        Ok(_) => {
+                            // If this is the last reference to the task, we need to either
+                            // schedule dropping its future or destroy it.
+                            if state & !(REFERENCE - 1) == 0 {
+                                if state & CLOSED == 0 {
+                                    ((*header).vtable.schedule)(ptr);
+                                } else {
+                                    ((*header).vtable.destroy)(ptr);
                                 }
-
-                                break;
                             }
-                            Err(s) => state = s,
+
+                            break;
                         }
+                        Err(s) => state = s,
                     }
                 }
             }
@@ -163,6 +165,16 @@
     }
 }
 
+impl<R> Drop for JoinHandle<R> {
+    fn drop(&mut self) {
+        let ptr = self.raw_task.as_ptr();
+        unsafe {
+            Self::cancel_raw(ptr);
+            Self::drop_raw(ptr);
+        }
+    }
+}
+
 impl<R> Future for JoinHandle<R> {
     type Output = Option<R>;
 
diff --git a/src/task.rs b/src/task.rs
index 10f9a34..0f7e4ea 100644
--- a/src/task.rs
+++ b/src/task.rs
@@ -254,18 +254,14 @@
         unsafe { ((*header).vtable.run)(ptr) }
     }
 
-    /// Cancels the task.
-    ///
-    /// When canceled, the task won't be scheduled again even if a [`Waker`] wakes it. An attempt
-    /// to run it won't do anything.
-    ///
-    /// [`Waker`]: https://doc.rust-lang.org/std/task/struct.Waker.html
-    pub fn cancel(&self) {
+    /// Returns a waker associated with this task.
+    pub fn waker(&self) -> Waker {
         let ptr = self.raw_task.as_ptr();
         let header = ptr as *const Header;
 
         unsafe {
-            (*header).cancel();
+            let raw_waker = ((*header).vtable.clone_waker)(ptr);
+            Waker::from_raw(raw_waker)
         }
     }
 
@@ -286,17 +282,6 @@
             raw_task: NonNull::new_unchecked(raw as *mut ()),
         }
     }
-
-    /// Returns a waker associated with this task.
-    pub fn waker(&self) -> Waker {
-        let ptr = self.raw_task.as_ptr();
-        let header = ptr as *const Header;
-
-        unsafe {
-            let raw_waker = ((*header).vtable.clone_waker)(ptr);
-            Waker::from_raw(raw_waker)
-        }
-    }
 }
 
 impl Drop for Task {
diff --git a/tests/basic.rs b/tests/basic.rs
index 14621fe..47dd075 100644
--- a/tests/basic.rs
+++ b/tests/basic.rs
@@ -79,7 +79,7 @@
 }
 
 #[test]
-fn cancel_and_drop_handle() {
+fn drop_and_detach() {
     future!(f, POLL, DROP_F);
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
@@ -89,13 +89,26 @@
     assert_eq!(DROP_F.load(), 0);
     assert_eq!(DROP_S.load(), 0);
 
-    task.cancel();
+    drop(task);
     assert_eq!(POLL.load(), 0);
     assert_eq!(SCHEDULE.load(), 0);
-    assert_eq!(DROP_F.load(), 0);
+    assert_eq!(DROP_F.load(), 1);
     assert_eq!(DROP_S.load(), 0);
 
-    drop(handle);
+    handle.detach();
+    assert_eq!(POLL.load(), 0);
+    assert_eq!(SCHEDULE.load(), 0);
+    assert_eq!(DROP_F.load(), 1);
+    assert_eq!(DROP_S.load(), 1);
+}
+
+#[test]
+fn detach_and_drop() {
+    future!(f, POLL, DROP_F);
+    schedule!(s, SCHEDULE, DROP_S);
+    let (task, handle) = async_task::spawn(f, s);
+
+    handle.detach();
     assert_eq!(POLL.load(), 0);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 0);
@@ -109,12 +122,12 @@
 }
 
 #[test]
-fn run_and_drop_handle() {
+fn detach_and_run() {
     future!(f, POLL, DROP_F);
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
 
-    drop(handle);
+    handle.detach();
     assert_eq!(POLL.load(), 0);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 0);
@@ -128,18 +141,18 @@
 }
 
 #[test]
-fn drop_handle_and_run() {
+fn run_and_detach() {
     future!(f, POLL, DROP_F);
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
 
-    drop(handle);
-    assert_eq!(POLL.load(), 0);
+    task.run();
+    assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 0);
-    assert_eq!(DROP_F.load(), 0);
+    assert_eq!(DROP_F.load(), 1);
     assert_eq!(DROP_S.load(), 0);
 
-    task.run();
+    handle.detach();
     assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 1);
@@ -152,12 +165,6 @@
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
 
-    handle.cancel();
-    assert_eq!(POLL.load(), 0);
-    assert_eq!(SCHEDULE.load(), 0);
-    assert_eq!(DROP_F.load(), 0);
-    assert_eq!(DROP_S.load(), 0);
-
     drop(handle);
     assert_eq!(POLL.load(), 0);
     assert_eq!(SCHEDULE.load(), 0);
@@ -183,12 +190,6 @@
     assert_eq!(DROP_F.load(), 1);
     assert_eq!(DROP_S.load(), 0);
 
-    handle.cancel();
-    assert_eq!(POLL.load(), 1);
-    assert_eq!(SCHEDULE.load(), 0);
-    assert_eq!(DROP_F.load(), 1);
-    assert_eq!(DROP_S.load(), 0);
-
     drop(handle);
     assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 0);
@@ -200,31 +201,28 @@
 fn cancel_and_poll() {
     future!(f, POLL, DROP_F);
     schedule!(s, SCHEDULE, DROP_S);
-    let (task, handle) = async_task::spawn(f, s);
+    let (task, mut handle) = async_task::spawn(f, s);
 
-    handle.cancel();
+    assert!((&mut handle).now_or_never().is_none());
     assert_eq!(POLL.load(), 0);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 0);
     assert_eq!(DROP_S.load(), 0);
 
-    let mut handle = handle;
-    assert!((&mut handle).now_or_never().is_none());
-
     task.run();
-    assert_eq!(POLL.load(), 0);
+    assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 1);
     assert_eq!(DROP_S.load(), 0);
 
     assert!((&mut handle).now_or_never().is_some());
-    assert_eq!(POLL.load(), 0);
+    assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 1);
     assert_eq!(DROP_S.load(), 0);
 
     drop(handle);
-    assert_eq!(POLL.load(), 0);
+    assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 1);
     assert_eq!(DROP_S.load(), 1);
diff --git a/tests/join.rs b/tests/join.rs
index e7f0972..ca0ef54 100644
--- a/tests/join.rs
+++ b/tests/join.rs
@@ -96,14 +96,13 @@
 }
 
 #[test]
-fn cancel_and_join() {
+fn drop_and_join() {
     future!(f, POLL, DROP_F, DROP_O);
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
 
     assert_eq!(DROP_O.load(), 0);
 
-    task.cancel();
     drop(task);
     assert_eq!(DROP_O.load(), 0);
 
@@ -135,14 +134,14 @@
 }
 
 #[test]
-fn drop_handle_and_run() {
+fn detach_and_run() {
     future!(f, POLL, DROP_F, DROP_O);
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
 
     assert_eq!(DROP_O.load(), 0);
 
-    drop(handle);
+    handle.detach();
     assert_eq!(DROP_O.load(), 0);
 
     task.run();
@@ -178,7 +177,7 @@
     assert_eq!(DROP_S.load(), 0);
     assert_eq!(DROP_O.load(), 1);
 
-    drop(handle);
+    handle.detach();
     assert_eq!(DROP_S.load(), 1);
 }
 
@@ -191,8 +190,6 @@
     crossbeam::scope(|scope| {
         scope.spawn(|_| {
             thread::sleep(ms(200));
-
-            task.cancel();
             drop(task);
 
             thread::sleep(ms(400));
@@ -292,7 +289,7 @@
 
     crossbeam::scope(|scope| {
         scope.spawn(|_| {
-            thread::sleep(ms(400));
+            thread::sleep(ms(200));
 
             task.run();
             assert_eq!(POLL.load(), 0);
@@ -308,13 +305,6 @@
         assert_eq!(DROP_S.load(), 0);
         assert_eq!(DROP_O.load(), 0);
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 0);
-        assert_eq!(SCHEDULE.load(), 0);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(DROP_O.load(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 0);
         assert_eq!(SCHEDULE.load(), 0);
@@ -351,13 +341,6 @@
 
         thread::sleep(ms(400));
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 1);
-        assert_eq!(SCHEDULE.load(), 0);
-        assert_eq!(DROP_F.load(), 1);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(DROP_O.load(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 1);
         assert_eq!(SCHEDULE.load(), 0);
diff --git a/tests/panic.rs b/tests/panic.rs
index 19c5f2b..6641025 100644
--- a/tests/panic.rs
+++ b/tests/panic.rs
@@ -102,12 +102,6 @@
 
         thread::sleep(ms(200));
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 1);
-        assert_eq!(SCHEDULE.load(), 0);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 1);
         assert_eq!(SCHEDULE.load(), 0);
@@ -219,7 +213,7 @@
 }
 
 #[test]
-fn drop_handle_during_run() {
+fn detach_during_run() {
     future!(f, POLL, DROP_F);
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
@@ -235,7 +229,7 @@
 
         thread::sleep(ms(200));
 
-        drop(handle);
+        handle.detach();
         assert_eq!(POLL.load(), 1);
         assert_eq!(SCHEDULE.load(), 0);
         assert_eq!(DROP_F.load(), 0);
diff --git a/tests/ready.rs b/tests/ready.rs
index 5f0efe1..12b3f06 100644
--- a/tests/ready.rs
+++ b/tests/ready.rs
@@ -106,13 +106,19 @@
             assert_eq!(POLL.load(), 1);
             assert_eq!(SCHEDULE.load(), 0);
             assert_eq!(DROP_F.load(), 1);
-            assert_eq!(DROP_S.load(), 0);
+            assert_eq!(DROP_S.load(), 1);
             assert_eq!(DROP_O.load(), 1);
         });
 
         thread::sleep(ms(200));
 
-        handle.cancel();
+        assert_eq!(POLL.load(), 1);
+        assert_eq!(SCHEDULE.load(), 0);
+        assert_eq!(DROP_F.load(), 0);
+        assert_eq!(DROP_S.load(), 0);
+        assert_eq!(DROP_O.load(), 0);
+
+        drop(handle);
         assert_eq!(POLL.load(), 1);
         assert_eq!(SCHEDULE.load(), 0);
         assert_eq!(DROP_F.load(), 0);
@@ -124,13 +130,6 @@
         assert_eq!(POLL.load(), 1);
         assert_eq!(SCHEDULE.load(), 0);
         assert_eq!(DROP_F.load(), 1);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(DROP_O.load(), 1);
-
-        drop(handle);
-        assert_eq!(POLL.load(), 1);
-        assert_eq!(SCHEDULE.load(), 0);
-        assert_eq!(DROP_F.load(), 1);
         assert_eq!(DROP_S.load(), 1);
         assert_eq!(DROP_O.load(), 1);
     })
@@ -151,6 +150,7 @@
             assert_eq!(DROP_F.load(), 1);
 
             thread::sleep(ms(200));
+
             assert_eq!(DROP_S.load(), 1);
         });
 
@@ -163,6 +163,7 @@
         assert_eq!(DROP_O.load(), 1);
 
         thread::sleep(ms(200));
+
         assert_eq!(DROP_S.load(), 1);
     })
     .unwrap();
@@ -198,7 +199,7 @@
 }
 
 #[test]
-fn drop_handle_during_run() {
+fn detach_during_run() {
     future!(f, POLL, DROP_F, DROP_O);
     schedule!(s, SCHEDULE, DROP_S);
     let (task, handle) = async_task::spawn(f, s);
@@ -215,7 +216,7 @@
 
         thread::sleep(ms(200));
 
-        drop(handle);
+        handle.detach();
         assert_eq!(POLL.load(), 1);
         assert_eq!(SCHEDULE.load(), 0);
         assert_eq!(DROP_F.load(), 0);
diff --git a/tests/waker_panic.rs b/tests/waker_panic.rs
index b090d00..457e69b 100644
--- a/tests/waker_panic.rs
+++ b/tests/waker_panic.rs
@@ -132,7 +132,7 @@
         thread::sleep(ms(200));
 
         w.wake();
-        drop(handle);
+        handle.detach();
         assert_eq!(POLL.load(), 2);
         assert_eq!(SCHEDULE.load(), 1);
         assert_eq!(DROP_F.load(), 0);
@@ -174,13 +174,6 @@
 
         thread::sleep(ms(200));
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 2);
-        assert_eq!(SCHEDULE.load(), 1);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(chan.len(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 2);
         assert_eq!(SCHEDULE.load(), 1);
@@ -230,13 +223,6 @@
         assert_eq!(DROP_S.load(), 0);
         assert_eq!(chan.len(), 0);
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 2);
-        assert_eq!(SCHEDULE.load(), 1);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(chan.len(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 2);
         assert_eq!(SCHEDULE.load(), 1);
@@ -279,13 +265,6 @@
 
         thread::sleep(ms(200));
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 2);
-        assert_eq!(SCHEDULE.load(), 1);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(chan.len(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 2);
         assert_eq!(SCHEDULE.load(), 1);
diff --git a/tests/waker_pending.rs b/tests/waker_pending.rs
index 8887264..683e595 100644
--- a/tests/waker_pending.rs
+++ b/tests/waker_pending.rs
@@ -164,13 +164,6 @@
 
         thread::sleep(ms(200));
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 2);
-        assert_eq!(SCHEDULE.load(), 1);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(chan.len(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 2);
         assert_eq!(SCHEDULE.load(), 1);
@@ -220,13 +213,6 @@
         assert_eq!(DROP_S.load(), 0);
         assert_eq!(chan.len(), 0);
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 2);
-        assert_eq!(SCHEDULE.load(), 1);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(chan.len(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 2);
         assert_eq!(SCHEDULE.load(), 1);
@@ -269,13 +255,6 @@
 
         thread::sleep(ms(200));
 
-        handle.cancel();
-        assert_eq!(POLL.load(), 2);
-        assert_eq!(SCHEDULE.load(), 1);
-        assert_eq!(DROP_F.load(), 0);
-        assert_eq!(DROP_S.load(), 0);
-        assert_eq!(chan.len(), 0);
-
         drop(handle);
         assert_eq!(POLL.load(), 2);
         assert_eq!(SCHEDULE.load(), 1);
@@ -310,7 +289,7 @@
     task.run();
     let w = waker();
 
-    drop(handle);
+    handle.detach();
     assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 0);
     assert_eq!(DROP_F.load(), 0);
@@ -346,7 +325,7 @@
     assert_eq!(DROP_S.load(), 0);
     assert_eq!(chan.len(), 0);
 
-    handle.cancel();
+    drop(handle);
     assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 1);
     assert_eq!(DROP_F.load(), 0);
@@ -357,13 +336,6 @@
     assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 1);
     assert_eq!(DROP_F.load(), 1);
-    assert_eq!(DROP_S.load(), 0);
-    assert_eq!(chan.len(), 0);
-
-    drop(handle);
-    assert_eq!(POLL.load(), 1);
-    assert_eq!(SCHEDULE.load(), 1);
-    assert_eq!(DROP_F.load(), 1);
     assert_eq!(DROP_S.load(), 1);
     assert_eq!(chan.len(), 0);
 }
@@ -382,7 +354,7 @@
     assert_eq!(DROP_S.load(), 0);
     assert_eq!(chan.len(), 0);
 
-    drop(handle);
+    handle.detach();
     assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 1);
     assert_eq!(DROP_F.load(), 0);
diff --git a/tests/waker_ready.rs b/tests/waker_ready.rs
index bf92960..b97425a 100644
--- a/tests/waker_ready.rs
+++ b/tests/waker_ready.rs
@@ -109,7 +109,8 @@
 fn wake() {
     future!(f, waker, POLL, DROP_F);
     schedule!(s, chan, SCHEDULE, DROP_S);
-    let (mut task, _) = async_task::spawn(f, s);
+    let (mut task, handle) = async_task::spawn(f, s);
+    handle.detach();
 
     assert!(chan.is_empty());
 
@@ -147,7 +148,8 @@
 fn wake_by_ref() {
     future!(f, waker, POLL, DROP_F);
     schedule!(s, chan, SCHEDULE, DROP_S);
-    let (mut task, _) = async_task::spawn(f, s);
+    let (mut task, handle) = async_task::spawn(f, s);
+    handle.detach();
 
     assert!(chan.is_empty());
 
@@ -185,7 +187,8 @@
 fn clone() {
     future!(f, waker, POLL, DROP_F);
     schedule!(s, chan, SCHEDULE, DROP_S);
-    let (mut task, _) = async_task::spawn(f, s);
+    let (mut task, handle) = async_task::spawn(f, s);
+    handle.detach();
 
     task.run();
     assert_eq!(POLL.load(), 1);
@@ -220,10 +223,11 @@
 }
 
 #[test]
-fn wake_canceled() {
+fn wake_dropped() {
     future!(f, waker, POLL, DROP_F);
     schedule!(s, chan, SCHEDULE, DROP_S);
-    let (task, _) = async_task::spawn(f, s);
+    let (task, handle) = async_task::spawn(f, s);
+    handle.detach();
 
     task.run();
     assert_eq!(POLL.load(), 1);
@@ -235,7 +239,7 @@
     let w = waker();
 
     w.wake_by_ref();
-    chan.recv().unwrap().cancel();
+    drop(chan.recv().unwrap());
     assert_eq!(POLL.load(), 1);
     assert_eq!(SCHEDULE.load(), 1);
     assert_eq!(DROP_F.load(), 1);
@@ -254,7 +258,8 @@
 fn wake_completed() {
     future!(f, waker, POLL, DROP_F);
     schedule!(s, chan, SCHEDULE, DROP_S);
-    let (task, _) = async_task::spawn(f, s);
+    let (task, handle) = async_task::spawn(f, s);
+    handle.detach();
 
     task.run();
     let w = waker();