about summary refs log tree commit diff
path: root/tests/ui/try-trait
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/try-trait')
-rw-r--r--tests/ui/try-trait/bad-interconversion.rs48
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr103
-rw-r--r--tests/ui/try-trait/option-to-result.rs13
-rw-r--r--tests/ui/try-trait/option-to-result.stderr31
-rw-r--r--tests/ui/try-trait/try-as-monad.rs24
-rw-r--r--tests/ui/try-trait/try-on-option-diagnostics.rs47
-rw-r--r--tests/ui/try-trait/try-on-option-diagnostics.stderr47
-rw-r--r--tests/ui/try-trait/try-on-option.rs13
-rw-r--r--tests/ui/try-trait/try-on-option.stderr28
-rw-r--r--tests/ui/try-trait/try-operator-custom.rs91
-rw-r--r--tests/ui/try-trait/try-operator-on-main.rs22
-rw-r--r--tests/ui/try-trait/try-operator-on-main.stderr53
-rw-r--r--tests/ui/try-trait/try-poll.rs50
-rw-r--r--tests/ui/try-trait/yeet-for-option.rs11
-rw-r--r--tests/ui/try-trait/yeet-for-result.rs11
15 files changed, 592 insertions, 0 deletions
diff --git a/tests/ui/try-trait/bad-interconversion.rs b/tests/ui/try-trait/bad-interconversion.rs
new file mode 100644
index 00000000000..385f5510fb4
--- /dev/null
+++ b/tests/ui/try-trait/bad-interconversion.rs
@@ -0,0 +1,48 @@
+#![feature(control_flow_enum)]
+
+use std::ops::ControlFlow;
+
+fn result_to_result() -> Result<u64, u8> {
+    Ok(Err(123_i32)?)
+    //~^ ERROR `?` couldn't convert the error to `u8`
+}
+
+fn option_to_result() -> Result<u64, String> {
+    Some(3)?;
+    //~^ ERROR the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+    Ok(10)
+}
+
+fn control_flow_to_result() -> Result<u64, String> {
+    Ok(ControlFlow::Break(123)?)
+    //~^ ERROR the `?` operator can only be used on `Result`s in a function that returns `Result`
+}
+
+fn result_to_option() -> Option<u16> {
+    Some(Err("hello")?)
+    //~^ ERROR the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
+}
+
+fn control_flow_to_option() -> Option<u64> {
+    Some(ControlFlow::Break(123)?)
+    //~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option`
+}
+
+fn result_to_control_flow() -> ControlFlow<String> {
+    ControlFlow::Continue(Err("hello")?)
+    //~^ ERROR the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
+}
+
+fn option_to_control_flow() -> ControlFlow<u64> {
+    Some(3)?;
+    //~^ ERROR the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
+    ControlFlow::Break(10)
+}
+
+fn control_flow_to_control_flow() -> ControlFlow<i64> {
+    ControlFlow::Break(4_u8)?;
+    //~^ ERROR the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s
+    ControlFlow::Continue(())
+}
+
+fn main() {}
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
new file mode 100644
index 00000000000..a49630adb95
--- /dev/null
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -0,0 +1,103 @@
+error[E0277]: `?` couldn't convert the error to `u8`
+  --> $DIR/bad-interconversion.rs:6:20
+   |
+LL | fn result_to_result() -> Result<u64, u8> {
+   |                          --------------- expected `u8` because of this
+LL |     Ok(Err(123_i32)?)
+   |                    ^ the trait `From<i32>` is not implemented for `u8`
+   |
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
+   = help: the following other types implement trait `From<T>`:
+             <u8 as From<NonZeroU8>>
+             <u8 as From<bool>>
+   = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
+
+error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+  --> $DIR/bad-interconversion.rs:11:12
+   |
+LL | fn option_to_result() -> Result<u64, String> {
+   | -------------------------------------------- this function returns a `Result`
+LL |     Some(3)?;
+   |            ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
+   = help: the following other types implement trait `FromResidual<R>`:
+             <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
+
+error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
+  --> $DIR/bad-interconversion.rs:17:31
+   |
+LL | fn control_flow_to_result() -> Result<u64, String> {
+   | -------------------------------------------------- this function returns a `Result`
+LL |     Ok(ControlFlow::Break(123)?)
+   |                               ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
+   |
+   = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
+   = help: the following other types implement trait `FromResidual<R>`:
+             <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
+
+error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
+  --> $DIR/bad-interconversion.rs:22:22
+   |
+LL | fn result_to_option() -> Option<u16> {
+   | ------------------------------------ this function returns an `Option`
+LL |     Some(Err("hello")?)
+   |                      ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
+   |
+   = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
+   = help: the following other types implement trait `FromResidual<R>`:
+             <Option<T> as FromResidual<Yeet<()>>>
+             <Option<T> as FromResidual>
+
+error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
+  --> $DIR/bad-interconversion.rs:27:33
+   |
+LL | fn control_flow_to_option() -> Option<u64> {
+   | ------------------------------------------ this function returns an `Option`
+LL |     Some(ControlFlow::Break(123)?)
+   |                                 ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
+   |
+   = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
+   = help: the following other types implement trait `FromResidual<R>`:
+             <Option<T> as FromResidual<Yeet<()>>>
+             <Option<T> as FromResidual>
+
+error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
+  --> $DIR/bad-interconversion.rs:32:39
+   |
+LL | fn result_to_control_flow() -> ControlFlow<String> {
+   | -------------------------------------------------- this function returns a `ControlFlow`
+LL |     ControlFlow::Continue(Err("hello")?)
+   |                                       ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
+   |
+   = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
+   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+
+error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
+  --> $DIR/bad-interconversion.rs:37:12
+   |
+LL | fn option_to_control_flow() -> ControlFlow<u64> {
+   | ----------------------------------------------- this function returns a `ControlFlow`
+LL |     Some(3)?;
+   |            ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
+   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+
+error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
+  --> $DIR/bad-interconversion.rs:43:29
+   |
+LL | fn control_flow_to_control_flow() -> ControlFlow<i64> {
+   | ----------------------------------------------------- this function returns a `ControlFlow`
+LL |     ControlFlow::Break(4_u8)?;
+   |                             ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
+   |
+   = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
+   = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
+   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/try-trait/option-to-result.rs b/tests/ui/try-trait/option-to-result.rs
new file mode 100644
index 00000000000..45aaf361a9c
--- /dev/null
+++ b/tests/ui/try-trait/option-to-result.rs
@@ -0,0 +1,13 @@
+fn main(){ }
+
+fn test_result() -> Result<(),()> {
+    let a:Option<()> = Some(());
+    a?;//~ ERROR the `?` operator can only be used
+    Ok(())
+}
+
+fn test_option() -> Option<i32>{
+    let a:Result<i32, i32> = Ok(5);
+    a?;//~ ERROR the `?` operator can only be used
+    Some(5)
+}
diff --git a/tests/ui/try-trait/option-to-result.stderr b/tests/ui/try-trait/option-to-result.stderr
new file mode 100644
index 00000000000..fabc1ff2c76
--- /dev/null
+++ b/tests/ui/try-trait/option-to-result.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+  --> $DIR/option-to-result.rs:5:6
+   |
+LL | fn test_result() -> Result<(),()> {
+   | --------------------------------- this function returns a `Result`
+LL |     let a:Option<()> = Some(());
+LL |     a?;
+   |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
+   = help: the following other types implement trait `FromResidual<R>`:
+             <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
+
+error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
+  --> $DIR/option-to-result.rs:11:6
+   |
+LL | fn test_option() -> Option<i32>{
+   | ------------------------------- this function returns an `Option`
+LL |     let a:Result<i32, i32> = Ok(5);
+LL |     a?;
+   |      ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
+   |
+   = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
+   = help: the following other types implement trait `FromResidual<R>`:
+             <Option<T> as FromResidual<Yeet<()>>>
+             <Option<T> as FromResidual>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/try-trait/try-as-monad.rs b/tests/ui/try-trait/try-as-monad.rs
new file mode 100644
index 00000000000..cf09838b304
--- /dev/null
+++ b/tests/ui/try-trait/try-as-monad.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+#![feature(try_trait_v2)]
+
+use std::ops::Try;
+
+fn monad_unit<T: Try>(x: <T as Try>::Output) -> T {
+    T::from_output(x)
+}
+
+fn monad_bind<T1: Try<Residual = R>, T2: Try<Residual = R>, R>(
+    mx: T1,
+    f: impl FnOnce(<T1 as Try>::Output) -> T2)
+-> T2 {
+    let x = mx?;
+    f(x)
+}
+
+fn main() {
+    let mx: Option<i32> = monad_unit(1);
+    let my = monad_bind(mx, |x| Some(x + 1));
+    let mz = monad_bind(my, |x| Some(-x));
+    assert_eq!(mz, Some(-2));
+}
diff --git a/tests/ui/try-trait/try-on-option-diagnostics.rs b/tests/ui/try-trait/try-on-option-diagnostics.rs
new file mode 100644
index 00000000000..7ffa0de6c0f
--- /dev/null
+++ b/tests/ui/try-trait/try-on-option-diagnostics.rs
@@ -0,0 +1,47 @@
+// edition:2018
+
+fn main() {}
+
+fn a_function() -> u32 {
+    let x: Option<u32> = None;
+    x?; //~ ERROR the `?` operator
+    22
+}
+
+fn a_closure() -> u32 {
+    let a_closure = || {
+        let x: Option<u32> = None;
+        x?; //~ ERROR the `?` operator
+        22
+    };
+    a_closure()
+}
+
+fn a_method() -> u32 {
+    struct S;
+
+    impl S {
+        fn a_method() {
+            let x: Option<u32> = None;
+            x?; //~ ERROR the `?` operator
+        }
+    }
+
+    S::a_method();
+    22
+}
+
+fn a_trait_method() -> u32 {
+    struct S;
+    trait T {
+        fn a_trait_method() {
+            let x: Option<u32> = None;
+            x?; //~ ERROR the `?` operator
+        }
+    }
+
+    impl T for S { }
+
+    S::a_trait_method();
+    22
+}
diff --git a/tests/ui/try-trait/try-on-option-diagnostics.stderr b/tests/ui/try-trait/try-on-option-diagnostics.stderr
new file mode 100644
index 00000000000..9ee540c79fd
--- /dev/null
+++ b/tests/ui/try-trait/try-on-option-diagnostics.stderr
@@ -0,0 +1,47 @@
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:7:6
+   |
+LL | fn a_function() -> u32 {
+   | ---------------------- this function should return `Result` or `Option` to accept `?`
+LL |     let x: Option<u32> = None;
+LL |     x?;
+   |      ^ cannot use the `?` operator in a function that returns `u32`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+
+error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:14:10
+   |
+LL |     let a_closure = || {
+   |                     -- this function should return `Result` or `Option` to accept `?`
+LL |         let x: Option<u32> = None;
+LL |         x?;
+   |          ^ cannot use the `?` operator in a closure that returns `{integer}`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
+
+error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:26:14
+   |
+LL |         fn a_method() {
+   |         ------------- this function should return `Result` or `Option` to accept `?`
+LL |             let x: Option<u32> = None;
+LL |             x?;
+   |              ^ cannot use the `?` operator in a method that returns `()`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
+
+error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:39:14
+   |
+LL |         fn a_trait_method() {
+   |         ------------------- this function should return `Result` or `Option` to accept `?`
+LL |             let x: Option<u32> = None;
+LL |             x?;
+   |              ^ cannot use the `?` operator in a trait method that returns `()`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/try-trait/try-on-option.rs b/tests/ui/try-trait/try-on-option.rs
new file mode 100644
index 00000000000..8519932a634
--- /dev/null
+++ b/tests/ui/try-trait/try-on-option.rs
@@ -0,0 +1,13 @@
+fn main() {}
+
+fn foo() -> Result<u32, ()> {
+    let x: Option<u32> = None;
+    x?; //~ ERROR the `?` operator
+    Ok(22)
+}
+
+fn bar() -> u32 {
+    let x: Option<u32> = None;
+    x?; //~ ERROR the `?` operator
+    22
+}
diff --git a/tests/ui/try-trait/try-on-option.stderr b/tests/ui/try-trait/try-on-option.stderr
new file mode 100644
index 00000000000..fad6a1fe823
--- /dev/null
+++ b/tests/ui/try-trait/try-on-option.stderr
@@ -0,0 +1,28 @@
+error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+  --> $DIR/try-on-option.rs:5:6
+   |
+LL | fn foo() -> Result<u32, ()> {
+   | --------------------------- this function returns a `Result`
+LL |     let x: Option<u32> = None;
+LL |     x?;
+   |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
+   = help: the following other types implement trait `FromResidual<R>`:
+             <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option.rs:11:6
+   |
+LL | fn bar() -> u32 {
+   | --------------- this function should return `Result` or `Option` to accept `?`
+LL |     let x: Option<u32> = None;
+LL |     x?;
+   |      ^ cannot use the `?` operator in a function that returns `u32`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/try-trait/try-operator-custom.rs b/tests/ui/try-trait/try-operator-custom.rs
new file mode 100644
index 00000000000..45636a7fced
--- /dev/null
+++ b/tests/ui/try-trait/try-operator-custom.rs
@@ -0,0 +1,91 @@
+// run-pass
+
+#![feature(control_flow_enum)]
+#![feature(try_trait_v2)]
+
+use std::ops::{ControlFlow, FromResidual, Try};
+
+enum MyResult<T, U> {
+    Awesome(T),
+    Terrible(U)
+}
+
+enum Never {}
+
+impl<U, V> Try for MyResult<U, V> {
+    type Output = U;
+    type Residual = MyResult<Never, V>;
+
+    fn from_output(u: U) -> MyResult<U, V> {
+        MyResult::Awesome(u)
+    }
+
+    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+        match self {
+            MyResult::Awesome(u) => ControlFlow::Continue(u),
+            MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)),
+        }
+    }
+}
+
+impl<U, V, W> FromResidual<MyResult<Never, V>> for MyResult<U, W> where V: Into<W> {
+    fn from_residual(x: MyResult<Never, V>) -> Self {
+        match x {
+            MyResult::Awesome(u) => match u {},
+            MyResult::Terrible(e) => MyResult::Terrible(e.into()),
+        }
+    }
+}
+
+type ResultResidual<E> = Result<std::convert::Infallible, E>;
+
+impl<U, V, W> FromResidual<ResultResidual<V>> for MyResult<U, W> where V: Into<W> {
+    fn from_residual(x: ResultResidual<V>) -> Self {
+        match x {
+            Ok(v) => match v {}
+            Err(e) => MyResult::Terrible(e.into()),
+        }
+    }
+}
+
+impl<U, V, W> FromResidual<MyResult<Never, V>> for Result<U, W> where V: Into<W> {
+    fn from_residual(x: MyResult<Never, V>) -> Self {
+        match x {
+            MyResult::Awesome(u) => match u {},
+            MyResult::Terrible(e) => Err(e.into()),
+        }
+    }
+}
+
+fn f(x: i32) -> Result<i32, String> {
+    if x == 0 {
+        Ok(42)
+    } else {
+        let y = g(x)?;
+        Ok(y)
+    }
+}
+
+fn g(x: i32) -> MyResult<i32, String> {
+    let _y = f(x - 1)?;
+    MyResult::Terrible("Hello".to_owned())
+}
+
+fn h() -> MyResult<i32, String> {
+    let a: Result<i32, &'static str> = Err("Hello");
+    let b = a?;
+    MyResult::Awesome(b)
+}
+
+fn i() -> MyResult<i32, String> {
+    let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
+    let b = a?;
+    MyResult::Awesome(b)
+}
+
+fn main() {
+    assert!(f(0) == Ok(42));
+    assert!(f(10) == Err("Hello".to_owned()));
+    let _ = h();
+    let _ = i();
+}
diff --git a/tests/ui/try-trait/try-operator-on-main.rs b/tests/ui/try-trait/try-operator-on-main.rs
new file mode 100644
index 00000000000..3b364f7e7d3
--- /dev/null
+++ b/tests/ui/try-trait/try-operator-on-main.rs
@@ -0,0 +1,22 @@
+#![feature(try_trait_v2)]
+
+use std::ops::Try;
+
+fn main() {
+    // error for a `Try` type on a non-`Try` fn
+    std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
+
+    // a non-`Try` type on a non-`Try` fn
+    ()?; //~ ERROR the `?` operator can only be applied to
+    //~^ ERROR the `?` operator can only be used in a function that
+
+    // an unrelated use of `Try`
+    try_trait_generic::<()>(); //~ ERROR the trait bound
+}
+
+fn try_trait_generic<T: Try>() -> T {
+    // and a non-`Try` object on a `Try` fn.
+    ()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
+
+    loop {}
+}
diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr
new file mode 100644
index 00000000000..7cd38e0cf95
--- /dev/null
+++ b/tests/ui/try-trait/try-operator-on-main.stderr
@@ -0,0 +1,53 @@
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-operator-on-main.rs:7:31
+   |
+LL | fn main() {
+   | --------- this function should return `Result` or `Option` to accept `?`
+LL |     // error for a `Try` type on a non-`Try` fn
+LL |     std::fs::File::open("foo")?;
+   |                               ^ cannot use the `?` operator in a function that returns `()`
+   |
+   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+  --> $DIR/try-operator-on-main.rs:10:5
+   |
+LL |     ()?;
+   |     ^^^ the `?` operator cannot be applied to type `()`
+   |
+   = help: the trait `Try` is not implemented for `()`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-operator-on-main.rs:10:7
+   |
+LL | fn main() {
+   | --------- this function should return `Result` or `Option` to accept `?`
+...
+LL |     ()?;
+   |       ^ cannot use the `?` operator in a function that returns `()`
+   |
+   = help: the trait `FromResidual<_>` is not implemented for `()`
+
+error[E0277]: the trait bound `(): Try` is not satisfied
+  --> $DIR/try-operator-on-main.rs:14:25
+   |
+LL |     try_trait_generic::<()>();
+   |                         ^^ the trait `Try` is not implemented for `()`
+   |
+note: required by a bound in `try_trait_generic`
+  --> $DIR/try-operator-on-main.rs:17:25
+   |
+LL | fn try_trait_generic<T: Try>() -> T {
+   |                         ^^^ required by this bound in `try_trait_generic`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+  --> $DIR/try-operator-on-main.rs:19:5
+   |
+LL |     ()?;
+   |     ^^^ the `?` operator cannot be applied to type `()`
+   |
+   = help: the trait `Try` is not implemented for `()`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/try-trait/try-poll.rs b/tests/ui/try-trait/try-poll.rs
new file mode 100644
index 00000000000..d42e51c7405
--- /dev/null
+++ b/tests/ui/try-trait/try-poll.rs
@@ -0,0 +1,50 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![allow(dead_code, unused)]
+
+use std::task::Poll;
+
+struct K;
+struct E;
+
+fn as_result() -> Result<(), E> {
+    // From Result
+    let K = Ok::<K, E>(K)?;
+
+    // From Poll<Result>
+    let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
+
+    // From Poll<Option<Result>>
+    let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
+
+    Ok(())
+}
+
+fn as_poll_result() -> Poll<Result<(), E>> {
+    // From Result
+    let K = Ok::<K, E>(K)?;
+
+    // From Poll<Result>
+    let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
+
+    // From Poll<Option<Result>>
+    let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
+
+    Poll::Ready(Ok(()))
+}
+
+fn as_poll_option_result() -> Poll<Option<Result<(), E>>> {
+    // From Result
+    let K = Ok::<K, E>(K)?;
+
+    // From Poll<Result>
+    let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
+
+    // From Poll<Option<Result>>
+    let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
+
+    Poll::Ready(Some(Ok(())))
+}
+
+fn main() {
+}
diff --git a/tests/ui/try-trait/yeet-for-option.rs b/tests/ui/try-trait/yeet-for-option.rs
new file mode 100644
index 00000000000..753fbc1dee7
--- /dev/null
+++ b/tests/ui/try-trait/yeet-for-option.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+#![feature(yeet_expr)]
+
+fn always_yeet() -> Option<String> {
+    do yeet;
+}
+
+fn main() {
+    assert_eq!(always_yeet(), None);
+}
diff --git a/tests/ui/try-trait/yeet-for-result.rs b/tests/ui/try-trait/yeet-for-result.rs
new file mode 100644
index 00000000000..b7b113797cd
--- /dev/null
+++ b/tests/ui/try-trait/yeet-for-result.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+#![feature(yeet_expr)]
+
+fn always_yeet() -> Result<i32, String> {
+    do yeet "hello";
+}
+
+fn main() {
+    assert_eq!(always_yeet(), Err("hello".to_string()));
+}