Implement the alternative try desugaring
This commit is contained in:
parent
20f1c045c4
commit
86c3ba754a
10 changed files with 41 additions and 21 deletions
|
|
@ -1923,7 +1923,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
/// ControlFlow::Break(residual) =>
|
||||
/// #[allow(unreachable_code)]
|
||||
/// // If there is an enclosing `try {...}`:
|
||||
/// break 'catch_target Try::from_residual(residual),
|
||||
/// break 'catch_target Residual::into_try_type(residual),
|
||||
/// // Otherwise:
|
||||
/// return Try::from_residual(residual),
|
||||
/// }
|
||||
|
|
@ -1973,7 +1973,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
|
||||
let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
|
||||
let from_residual_expr = self.wrap_in_try_constructor(
|
||||
hir::LangItem::TryTraitFromResidual,
|
||||
if self.catch_scope.is_some() {
|
||||
hir::LangItem::ResidualIntoTryType
|
||||
} else {
|
||||
hir::LangItem::TryTraitFromResidual
|
||||
},
|
||||
try_span,
|
||||
self.arena.alloc(residual_expr),
|
||||
unstable_span,
|
||||
|
|
|
|||
|
|
@ -183,7 +183,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
impl_trait_defs: Vec::new(),
|
||||
impl_trait_bounds: Vec::new(),
|
||||
allow_contracts: [sym::contracts_internals].into(),
|
||||
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
|
||||
allow_try_trait: [
|
||||
sym::try_trait_v2,
|
||||
sym::try_trait_v2_residual,
|
||||
sym::yeet_desugar_details,
|
||||
]
|
||||
.into(),
|
||||
allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),
|
||||
allow_gen_future: if tcx.features().async_fn_track_caller() {
|
||||
[sym::gen_future, sym::closure_track_caller].into()
|
||||
|
|
|
|||
|
|
@ -372,6 +372,7 @@ language_item_table! {
|
|||
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
|
||||
ResidualIntoTryType, sym::into_try_type, into_try_type_fn, Target::Method(MethodKind::Trait { body: true }), GenericRequirement::None;
|
||||
|
||||
CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1260,6 +1260,7 @@ symbols! {
|
|||
into_async_iter_into_iter,
|
||||
into_future,
|
||||
into_iter,
|
||||
into_try_type,
|
||||
intra_doc_pointers,
|
||||
intrinsics,
|
||||
intrinsics_unaligned_volatile_load,
|
||||
|
|
@ -2280,6 +2281,7 @@ symbols! {
|
|||
try_from_fn,
|
||||
try_into,
|
||||
try_trait_v2,
|
||||
try_trait_v2_residual,
|
||||
try_update,
|
||||
tt,
|
||||
tuple,
|
||||
|
|
|
|||
|
|
@ -359,11 +359,20 @@ where
|
|||
/// and in the other direction,
|
||||
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
|
||||
pub const trait Residual<O> {
|
||||
#[rustc_const_unstable(feature = "const_try_residual", issue = "91285")]
|
||||
pub const trait Residual<O>: Sized {
|
||||
/// The "return" type of this meta-function.
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
type TryType: Try<Output = O, Residual = Self>;
|
||||
type TryType: [const] Try<Output = O, Residual = Self>;
|
||||
|
||||
/// Here for convenience in the `?` desugaring.
|
||||
/// Probably should not be stabilized, as it should never be overridden.
|
||||
/// (without a `final fn` of some form, cc RFC#3678)
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
#[lang = "into_try_type"]
|
||||
fn into_try_type(self) -> Self::TryType {
|
||||
FromResidual::from_residual(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ fn copy_specialization() -> Result<()> {
|
|||
"inner Take allowed reading beyond end of file, some bytes should be left"
|
||||
);
|
||||
|
||||
let mut sink = sink.into_inner()?;
|
||||
let mut sink = sink.into_inner().map_err(io::Error::from)?;
|
||||
sink.seek(SeekFrom::Start(0))?;
|
||||
let mut copied = Vec::new();
|
||||
sink.read_to_end(&mut copied)?;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fn option_traits(_1: Option<u32>) -> Option<u32> {
|
|||
}
|
||||
|
||||
bb3: {
|
||||
_0 = <Option<u32> as FromResidual<Option<Infallible>>>::from_residual(const Option::<Infallible>::None) -> [return: bb4, unwind unreachable];
|
||||
_0 = <Option<Infallible> as Residual<u32>>::into_try_type(const Option::<Infallible>::None) -> [return: bb4, unwind unreachable];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fn option_traits(_1: Option<u32>) -> Option<u32> {
|
|||
}
|
||||
|
||||
bb3: {
|
||||
_0 = <Option<u32> as FromResidual<Option<Infallible>>>::from_residual(const Option::<Infallible>::None) -> [return: bb4, unwind continue];
|
||||
_0 = <Option<Infallible> as Residual<u32>>::into_try_type(const Option::<Infallible>::None) -> [return: bb4, unwind continue];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
pub fn main() {
|
||||
let res: Result<u32, std::array::TryFromSliceError> = try {
|
||||
Err("")?; //~ ERROR `?` couldn't convert the error
|
||||
Err("")?; //~ ERROR mismatched types
|
||||
5
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
error[E0277]: `?` couldn't convert the error to `TryFromSliceError`
|
||||
--> $DIR/try-block-bad-type.rs:7:16
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/try-block-bad-type.rs:7:9
|
||||
|
|
||||
LL | Err("")?;
|
||||
| -------^ the trait `From<&str>` is not implemented for `TryFromSliceError`
|
||||
| |
|
||||
| this can't be annotated with `?` because it has type `Result<_, &str>`
|
||||
| ^^^^^^^^ expected `Result<u32, TryFromSliceError>`, found `Result<_, &str>`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
help: the trait `From<&str>` is not implemented for `TryFromSliceError`
|
||||
but trait `From<Infallible>` is implemented for it
|
||||
--> $SRC_DIR/core/src/array/mod.rs:LL:COL
|
||||
= help: for that trait implementation, expected `Infallible`, found `&str`
|
||||
= note: expected enum `Result<u32, TryFromSliceError>`
|
||||
found enum `Result<_, &str>`
|
||||
help: consider using `Result::expect` to unwrap the `Result<_, &str>` value, panicking if the value is a `Result::Err`
|
||||
|
|
||||
LL | Err("")?.expect("REASON");
|
||||
| +++++++++++++++++
|
||||
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
|
||||
--> $DIR/try-block-bad-type.rs:12:9
|
||||
|
|
@ -42,5 +41,5 @@ LL | let res: i32 = try { 5 };
|
|||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
Some errors have detailed explanations: E0271, E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue