@@ -115,6 +115,21 @@ use crate::ops::ControlFlow;
115
115
/// }
116
116
/// ```
117
117
#[ 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 = "?" ) ]
118
133
#[ cfg_attr( not( bootstrap) , lang = "Try" ) ]
119
134
pub trait Try : FromResidual {
120
135
/// The type of the value produced by `?` when *not* short-circuiting.
@@ -212,6 +227,70 @@ pub trait Try: FromResidual {
212
227
/// Every `Try` type needs to be recreatable from its own associated
213
228
/// `Residual` type, but can also have additional `FromResidual` implementations
214
229
/// 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
+ ) ]
215
294
#[ unstable( feature = "try_trait_v2" , issue = "84277" ) ]
216
295
pub trait FromResidual < R = <Self as Try >:: Residual > {
217
296
/// Constructs the type from a compatible `Residual` type.
0 commit comments