diff --git a/.travis.yml b/.travis.yml index db964a30fd..c19dd2c310 100644 --- a/.travis.yml +++ b/.travis.yml @@ -129,7 +129,7 @@ matrix: - name: cargo check (features) rust: nightly install: - - cargo install -Z install-upgrade cargo-hack + - cargo install cargo-hack script: # Check each specified feature works properly # * `--each-feature` - run for each feature which includes --no-default-features and default features of package diff --git a/futures-macro/src/join.rs b/futures-macro/src/join.rs index aaedc3e3ec..93b5a28cec 100644 --- a/futures-macro/src/join.rs +++ b/futures-macro/src/join.rs @@ -129,6 +129,8 @@ pub(crate) fn try_join(input: TokenStream) -> TokenStream { } else if unsafe { #futures_crate::core_reexport::pin::Pin::new_unchecked(&mut #fut) }.output_mut().unwrap().is_err() { // `.err().unwrap()` rather than `.unwrap_err()` so that we don't introduce // a `T: Debug` bound. + // Also, for an error type of ! any code after `err().unwrap()` is unreachable. + #[allow(unreachable_code)] return #futures_crate::core_reexport::task::Poll::Ready( #futures_crate::core_reexport::result::Result::Err( unsafe { #futures_crate::core_reexport::pin::Pin::new_unchecked(&mut #fut) }.take_output().unwrap().err().unwrap() @@ -141,6 +143,8 @@ pub(crate) fn try_join(input: TokenStream) -> TokenStream { quote! { // `.ok().unwrap()` rather than `.unwrap()` so that we don't introduce // an `E: Debug` bound. + // Also, for an ok type of ! any code after `ok().unwrap()` is unreachable. + #[allow(unreachable_code)] unsafe { #futures_crate::core_reexport::pin::Pin::new_unchecked(&mut #fut) }.take_output().unwrap().ok().unwrap(), } }); diff --git a/futures/tests/try_join.rs b/futures/tests/try_join.rs new file mode 100644 index 0000000000..a148657288 --- /dev/null +++ b/futures/tests/try_join.rs @@ -0,0 +1,23 @@ +#![deny(unreachable_code)] + +use futures::{try_join, executor::block_on}; + +#[test] +fn try_join_never_error() { + block_on(async { + let future1 = async { Ok::<(), !>(()) }; + let future2 = async { Ok::<(), !>(()) }; + try_join!(future1, future2) + }) + .unwrap(); +} + +#[test] +fn try_join_never_ok() { + block_on(async { + let future1 = async { Err::(()) }; + let future2 = async { Err::(()) }; + try_join!(future1, future2) + }) + .unwrap_err(); +}