@@ -115,6 +115,21 @@ use crate::ops::ControlFlow;
115115/// }
116116/// ```
117117#[ unstable( feature = "try_trait_v2" , issue = "84277" ) ]
118+ #[ rustc_on_unimplemented(
119+ on(
120+ all( from_method = "from_output" , from_desugaring = "TryBlock" ) ,
121+ message = "a `try` block must return `Result` or `Option` \
122+ (or another type that implements `{Try}`)",
123+ label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`" ,
124+ ) ,
125+ on(
126+ all( from_method = "branch" , from_desugaring = "QuestionMark" ) ,
127+ message = "the `?` operator can only be applied to values \
128+ that implement `{Try}`",
129+ label = "the `?` operator cannot be applied to type `{Self}`"
130+ )
131+ ) ]
132+ #[ doc( alias = "?" ) ]
118133#[ cfg_attr( not( bootstrap) , lang = "Try" ) ]
119134pub trait Try : FromResidual {
120135 /// The type of the value produced by `?` when *not* short-circuiting.
@@ -212,6 +227,70 @@ pub trait Try: FromResidual {
212227/// Every `Try` type needs to be recreatable from its own associated
213228/// `Residual` type, but can also have additional `FromResidual` implementations
214229/// to support interconversion with other `Try` types.
230+ #[ rustc_on_unimplemented(
231+ on(
232+ all(
233+ from_method = "from_residual" ,
234+ from_desugaring = "QuestionMark" ,
235+ _Self = "std::result::Result<T, E>" ,
236+ R = "std::option::Option<std::convert::Infallible>"
237+ ) ,
238+ message = "the `?` operator can only be used on `Result`s, not `Option`s, \
239+ in {ItemContext} that returns `Result`",
240+ label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`" ,
241+ enclosing_scope = "this function returns a `Result`"
242+ ) ,
243+ on(
244+ all(
245+ from_method = "from_residual" ,
246+ from_desugaring = "QuestionMark" ,
247+ _Self = "std::result::Result<T, E>" ,
248+ ) ,
249+ // There's a special error message in the trait selection code for
250+ // `From` in `?`, so this is not shown for result-in-result errors,
251+ // and thus it can be phrased more strongly than `ControlFlow`'s.
252+ message = "the `?` operator can only be used on `Result`s \
253+ in {ItemContext} that returns `Result`",
254+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`" ,
255+ enclosing_scope = "this function returns a `Result`"
256+ ) ,
257+ on(
258+ all(
259+ from_method = "from_residual" ,
260+ from_desugaring = "QuestionMark" ,
261+ _Self = "std::option::Option<T>" ,
262+ ) ,
263+ // `Option`-in-`Option` always works, as there's only one possible
264+ // residual, so this can also be phrased strongly.
265+ message = "the `?` operator can only be used on `Option`s \
266+ in {ItemContext} that returns `Option`",
267+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`" ,
268+ enclosing_scope = "this function returns an `Option`"
269+ ) ,
270+ on(
271+ all(
272+ from_method = "from_residual" ,
273+ from_desugaring = "QuestionMark" ,
274+ _Self = "std::ops::ControlFlow<B, C>" ,
275+ ) ,
276+ message = "the `?` operator can only be used on `ControlFlow<B, _>`s \
277+ in {ItemContext} that returns `ControlFlow<B, _>`",
278+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`" ,
279+ enclosing_scope = "this function returns a `ControlFlow`" ,
280+ note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
281+ ) ,
282+ on(
283+ all(
284+ from_method = "from_residual" ,
285+ from_desugaring = "QuestionMark"
286+ ) ,
287+ message = "the `?` operator can only be used in {ItemContext} \
288+ that returns `Result` or `Option` \
289+ (or another type that implements `{FromResidual}`)",
290+ label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`" ,
291+ enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
292+ ) ,
293+ ) ]
215294#[ unstable( feature = "try_trait_v2" , issue = "84277" ) ]
216295pub trait FromResidual < R = <Self as Try >:: Residual > {
217296 /// Constructs the type from a compatible `Residual` type.
0 commit comments