summaryrefslogtreecommitdiffstats
path: root/src/test/ui/try-trait
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/try-trait
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/try-trait')
-rw-r--r--src/test/ui/try-trait/bad-interconversion.rs48
-rw-r--r--src/test/ui/try-trait/bad-interconversion.stderr127
-rw-r--r--src/test/ui/try-trait/option-to-result.rs13
-rw-r--r--src/test/ui/try-trait/option-to-result.stderr35
-rw-r--r--src/test/ui/try-trait/try-as-monad.rs24
-rw-r--r--src/test/ui/try-trait/try-on-option-diagnostics.rs47
-rw-r--r--src/test/ui/try-trait/try-on-option-diagnostics.stderr54
-rw-r--r--src/test/ui/try-trait/try-on-option.rs13
-rw-r--r--src/test/ui/try-trait/try-on-option.stderr32
-rw-r--r--src/test/ui/try-trait/try-operator-custom.rs91
-rw-r--r--src/test/ui/try-trait/try-operator-on-main.rs22
-rw-r--r--src/test/ui/try-trait/try-operator-on-main.stderr63
-rw-r--r--src/test/ui/try-trait/try-poll.rs50
-rw-r--r--src/test/ui/try-trait/yeet-for-option.rs11
-rw-r--r--src/test/ui/try-trait/yeet-for-result.rs11
15 files changed, 641 insertions, 0 deletions
diff --git a/src/test/ui/try-trait/bad-interconversion.rs b/src/test/ui/try-trait/bad-interconversion.rs
new file mode 100644
index 000000000..385f5510f
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr
new file mode 100644
index 000000000..1dbf3ebdf
--- /dev/null
+++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -0,0 +1,127 @@
+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>`:
+ <f32 as From<i16>>
+ <f32 as From<i8>>
+ <f32 as From<u16>>
+ <f32 as From<u8>>
+ <f64 as From<f32>>
+ <f64 as From<i16>>
+ <f64 as From<i32>>
+ <f64 as From<i8>>
+ and 67 others
+ = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
+
+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> {
+LL | | Some(3)?;
+ | | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
+LL | |
+LL | | Ok(10)
+LL | | }
+ | |_- this function returns a `Result`
+ |
+ = 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> {
+LL | | Ok(ControlFlow::Break(123)?)
+ | | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
+LL | |
+LL | | }
+ | |_- this function returns a `Result`
+ |
+ = 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> {
+LL | | Some(Err("hello")?)
+ | | ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
+LL | |
+LL | | }
+ | |_- this function returns an `Option`
+ |
+ = 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> {
+LL | | Some(ControlFlow::Break(123)?)
+ | | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
+LL | |
+LL | | }
+ | |_- this function returns an `Option`
+ |
+ = 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> {
+LL | | ControlFlow::Continue(Err("hello")?)
+ | | ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
+LL | |
+LL | | }
+ | |_- this function returns a `ControlFlow`
+ |
+ = 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> {
+LL | | Some(3)?;
+ | | ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
+LL | |
+LL | | ControlFlow::Break(10)
+LL | | }
+ | |_- this function returns a `ControlFlow`
+ |
+ = 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> {
+LL | | ControlFlow::Break(4_u8)?;
+ | | ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
+LL | |
+LL | | ControlFlow::Continue(())
+LL | | }
+ | |_- this function returns a `ControlFlow`
+ |
+ = 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/src/test/ui/try-trait/option-to-result.rs b/src/test/ui/try-trait/option-to-result.rs
new file mode 100644
index 000000000..45aaf361a
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/option-to-result.stderr b/src/test/ui/try-trait/option-to-result.stderr
new file mode 100644
index 000000000..ae5c3ad62
--- /dev/null
+++ b/src/test/ui/try-trait/option-to-result.stderr
@@ -0,0 +1,35 @@
+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<(),()> {
+LL | | let a:Option<()> = Some(());
+LL | | a?;
+ | | ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
+LL | | Ok(())
+LL | | }
+ | |_- this function returns a `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>{
+LL | | let a:Result<i32, i32> = Ok(5);
+LL | | a?;
+ | | ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
+LL | | Some(5)
+LL | | }
+ | |_- this function returns an `Option`
+ |
+ = 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/src/test/ui/try-trait/try-as-monad.rs b/src/test/ui/try-trait/try-as-monad.rs
new file mode 100644
index 000000000..cf09838b3
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/try-on-option-diagnostics.rs b/src/test/ui/try-trait/try-on-option-diagnostics.rs
new file mode 100644
index 000000000..7ffa0de6c
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/try-on-option-diagnostics.stderr b/src/test/ui/try-trait/try-on-option-diagnostics.stderr
new file mode 100644
index 000000000..a6badd190
--- /dev/null
+++ b/src/test/ui/try-trait/try-on-option-diagnostics.stderr
@@ -0,0 +1,54 @@
+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 {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in a function that returns `u32`
+LL | | 22
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
+ |
+ = 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 = || {
+ | _____________________-
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in a closure that returns `{integer}`
+LL | | 22
+LL | | };
+ | |_____- this function should return `Result` or `Option` to accept `?`
+ |
+ = 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() {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in a method that returns `()`
+LL | | }
+ | |_________- this function should return `Result` or `Option` to accept `?`
+ |
+ = 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() {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in a trait method that returns `()`
+LL | | }
+ | |_________- this function should return `Result` or `Option` to accept `?`
+ |
+ = 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/src/test/ui/try-trait/try-on-option.rs b/src/test/ui/try-trait/try-on-option.rs
new file mode 100644
index 000000000..8519932a6
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr
new file mode 100644
index 000000000..ba85a7cad
--- /dev/null
+++ b/src/test/ui/try-trait/try-on-option.stderr
@@ -0,0 +1,32 @@
+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, ()> {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
+LL | | Ok(22)
+LL | | }
+ | |_- this function returns a `Result`
+ |
+ = 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 {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in a function that returns `u32`
+LL | | 22
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
+ |
+ = 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/src/test/ui/try-trait/try-operator-custom.rs b/src/test/ui/try-trait/try-operator-custom.rs
new file mode 100644
index 000000000..45636a7fc
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/try-operator-on-main.rs b/src/test/ui/try-trait/try-operator-on-main.rs
new file mode 100644
index 000000000..3b364f7e7
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/try-operator-on-main.stderr b/src/test/ui/try-trait/try-operator-on-main.stderr
new file mode 100644
index 000000000..ad55f40b5
--- /dev/null
+++ b/src/test/ui/try-trait/try-operator-on-main.stderr
@@ -0,0 +1,63 @@
+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() {
+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 `()`
+LL | |
+... |
+LL | | try_trait_generic::<()>();
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
+ |
+ = 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() {
+LL | | // error for a `Try` type on a non-`Try` fn
+LL | | std::fs::File::open("foo")?;
+LL | |
+LL | | // a non-`Try` type on a non-`Try` fn
+LL | | ()?;
+ | | ^ cannot use the `?` operator in a function that returns `()`
+... |
+LL | | try_trait_generic::<()>();
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
+ |
+ = 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/src/test/ui/try-trait/try-poll.rs b/src/test/ui/try-trait/try-poll.rs
new file mode 100644
index 000000000..d42e51c74
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/yeet-for-option.rs b/src/test/ui/try-trait/yeet-for-option.rs
new file mode 100644
index 000000000..753fbc1de
--- /dev/null
+++ b/src/test/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/src/test/ui/try-trait/yeet-for-result.rs b/src/test/ui/try-trait/yeet-for-result.rs
new file mode 100644
index 000000000..b7b113797
--- /dev/null
+++ b/src/test/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()));
+}