Better rustc_on_unimplemented, and UI test fixes

This commit is contained in:
Scott McMurray 2021-04-17 11:56:07 -07:00
parent 47b99485a3
commit 4a7ceea930
38 changed files with 564 additions and 266 deletions

View file

@ -187,7 +187,7 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
pub use self::r#try::Try;
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
pub use self::r#try::Try as TryV1;
pub(crate) use self::r#try::Try as TryV1;
#[unstable(feature = "try_trait_v2", issue = "84277")]
pub use self::try_trait::FromResidual;
@ -197,7 +197,7 @@ pub use self::try_trait::FromResidual;
pub use self::try_trait::Try;
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
pub use self::try_trait::Try as TryV2;
pub(crate) use self::try_trait::Try as TryV2;
#[unstable(feature = "generator_trait", issue = "43122")]
pub use self::generator::{Generator, GeneratorState};

View file

@ -115,6 +115,21 @@ use crate::ops::ControlFlow;
/// }
/// ```
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[rustc_on_unimplemented(
on(
all(from_method = "from_output", from_desugaring = "TryBlock"),
message = "a `try` block must return `Result` or `Option` \
(or another type that implements `{Try}`)",
label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`",
),
on(
all(from_method = "branch", from_desugaring = "QuestionMark"),
message = "the `?` operator can only be applied to values \
that implement `{Try}`",
label = "the `?` operator cannot be applied to type `{Self}`"
)
)]
#[doc(alias = "?")]
#[cfg_attr(not(bootstrap), lang = "Try")]
pub trait Try: FromResidual {
/// The type of the value produced by `?` when *not* short-circuiting.
@ -212,6 +227,70 @@ pub trait Try: FromResidual {
/// Every `Try` type needs to be recreatable from its own associated
/// `Residual` type, but can also have additional `FromResidual` implementations
/// to support interconversion with other `Try` types.
#[rustc_on_unimplemented(
on(
all(
from_method = "from_residual",
from_desugaring = "QuestionMark",
_Self = "std::result::Result<T, E>",
R = "std::option::Option<std::convert::Infallible>"
),
message = "the `?` operator can only be used on `Result`s, not `Option`s, \
in {ItemContext} that returns `Result`",
label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
enclosing_scope = "this function returns a `Result`"
),
on(
all(
from_method = "from_residual",
from_desugaring = "QuestionMark",
_Self = "std::result::Result<T, E>",
),
// There's a special error message in the trait selection code for
// `From` in `?`, so this is not shown for result-in-result errors,
// and thus it can be phrased more strongly than `ControlFlow`'s.
message = "the `?` operator can only be used on `Result`s \
in {ItemContext} that returns `Result`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
enclosing_scope = "this function returns a `Result`"
),
on(
all(
from_method = "from_residual",
from_desugaring = "QuestionMark",
_Self = "std::option::Option<T>",
),
// `Option`-in-`Option` always works, as there's only one possible
// residual, so this can also be phrased strongly.
message = "the `?` operator can only be used on `Option`s \
in {ItemContext} that returns `Option`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
enclosing_scope = "this function returns an `Option`"
),
on(
all(
from_method = "from_residual",
from_desugaring = "QuestionMark",
_Self = "std::ops::ControlFlow<B, C>",
),
message = "the `?` operator can only be used on `ControlFlow<B, _>`s \
in {ItemContext} that returns `ControlFlow<B, _>`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
enclosing_scope = "this function returns a `ControlFlow`",
note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
),
on(
all(
from_method = "from_residual",
from_desugaring = "QuestionMark"
),
message = "the `?` operator can only be used in {ItemContext} \
that returns `Result` or `Option` \
(or another type that implements `{FromResidual}`)",
label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
),
)]
#[unstable(feature = "try_trait_v2", issue = "84277")]
pub trait FromResidual<R = <Self as Try>::Residual> {
/// Constructs the type from a compatible `Residual` type.