@@ -222,7 +222,87 @@ pub trait Try: FromResidual {
222222/// Every `Try` type needs to be recreatable from its own associated
223223/// `Residual` type, but can also have additional `FromResidual` implementations
224224/// to support interconversion with other `Try` types.
225- #[ rustc_on_unimplemented(
225+ #[ cfg_attr( not( bootstrap) , rustc_on_unimplemented(
226+ on(
227+ all(
228+ from_desugaring = "QuestionMark" ,
229+ _Self = "std::result::Result<T, E>" ,
230+ R = "std::option::Option<std::convert::Infallible>"
231+ ) ,
232+ message = "the `?` operator can only be used on `Result`s, not `Option`s, \
233+ in {ItemContext} that returns `Result`",
234+ label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`" ,
235+ parent_label = "this function returns a `Result`"
236+ ) ,
237+ on(
238+ all(
239+ from_desugaring = "QuestionMark" ,
240+ _Self = "std::result::Result<T, E>" ,
241+ ) ,
242+ // There's a special error message in the trait selection code for
243+ // `From` in `?`, so this is not shown for result-in-result errors,
244+ // and thus it can be phrased more strongly than `ControlFlow`'s.
245+ message = "the `?` operator can only be used on `Result`s \
246+ in {ItemContext} that returns `Result`",
247+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`" ,
248+ parent_label = "this function returns a `Result`"
249+ ) ,
250+ on(
251+ all(
252+ from_desugaring = "QuestionMark" ,
253+ _Self = "std::option::Option<T>" ,
254+ R = "std::result::Result<T, E>" ,
255+ ) ,
256+ message = "the `?` operator can only be used on `Option`s, not `Result`s, \
257+ in {ItemContext} that returns `Option`",
258+ label = "use `.ok()?` if you want to discard the `{R}` error information" ,
259+ parent_label = "this function returns an `Option`"
260+ ) ,
261+ on(
262+ all(
263+ from_desugaring = "QuestionMark" ,
264+ _Self = "std::option::Option<T>" ,
265+ ) ,
266+ // `Option`-in-`Option` always works, as there's only one possible
267+ // residual, so this can also be phrased strongly.
268+ message = "the `?` operator can only be used on `Option`s \
269+ in {ItemContext} that returns `Option`",
270+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`" ,
271+ parent_label = "this function returns an `Option`"
272+ ) ,
273+ on(
274+ all(
275+ from_desugaring = "QuestionMark" ,
276+ _Self = "std::ops::ControlFlow<B, C>" ,
277+ R = "std::ops::ControlFlow<B, C>" ,
278+ ) ,
279+ message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
280+ can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
281+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`" ,
282+ parent_label = "this function returns a `ControlFlow`" ,
283+ note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
284+ ) ,
285+ on(
286+ all(
287+ from_desugaring = "QuestionMark" ,
288+ _Self = "std::ops::ControlFlow<B, C>" ,
289+ // `R` is not a `ControlFlow`, as that case was matched previously
290+ ) ,
291+ message = "the `?` operator can only be used on `ControlFlow`s \
292+ in {ItemContext} that returns `ControlFlow`",
293+ label = "this `?` produces `{R}`, which is incompatible with `{Self}`" ,
294+ parent_label = "this function returns a `ControlFlow`" ,
295+ ) ,
296+ on(
297+ all( from_desugaring = "QuestionMark" ) ,
298+ message = "the `?` operator can only be used in {ItemContext} \
299+ that returns `Result` or `Option` \
300+ (or another type that implements `{FromResidual}`)",
301+ label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`" ,
302+ parent_label = "this function should return `Result` or `Option` to accept `?`"
303+ ) ,
304+ ) ) ]
305+ #[ cfg_attr( bootstrap, rustc_on_unimplemented(
226306 on(
227307 all(
228308 from_desugaring = "QuestionMark" ,
@@ -301,7 +381,7 @@ pub trait Try: FromResidual {
301381 label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`" ,
302382 enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
303383 ) ,
304- ) ]
384+ ) ) ]
305385#[ rustc_diagnostic_item = "FromResidual" ]
306386#[ unstable( feature = "try_trait_v2" , issue = "84277" ) ]
307387pub trait FromResidual < R = <Self as Try >:: Residual > {
0 commit comments