diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2be2fca87c3c5..de2b8505d5c40 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -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, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9cb17ea67a377..1f36454ec861a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -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() diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index e454ed58699c9..0b236cebdcaa1 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -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); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b6d1ff2432d6b..b3428fa044ada 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -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, diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index e1f2ebcf4c289..374e59e5d75c0 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -359,11 +359,20 @@ where /// and in the other direction, /// ` as Residual>::TryType = Result`. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -#[rustc_const_unstable(feature = "const_try", issue = "74935")] -pub const trait Residual { +#[rustc_const_unstable(feature = "const_try_residual", issue = "91285")] +pub const trait Residual: Sized { /// The "return" type of this meta-function. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] - type TryType: Try; + type TryType: [const] Try; + + /// 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")] diff --git a/library/std/src/sys/pal/unix/kernel_copy/tests.rs b/library/std/src/sys/pal/unix/kernel_copy/tests.rs index 54d8f8ed2edd4..15dee768d928b 100644 --- a/library/std/src/sys/pal/unix/kernel_copy/tests.rs +++ b/library/std/src/sys/pal/unix/kernel_copy/tests.rs @@ -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)?; diff --git a/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-abort.mir index 5b401064dd0e1..94c430ea2df36 100644 --- a/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-abort.mir @@ -34,7 +34,7 @@ fn option_traits(_1: Option) -> Option { } bb3: { - _0 = as FromResidual>>::from_residual(const Option::::None) -> [return: bb4, unwind unreachable]; + _0 = as Residual>::into_try_type(const Option::::None) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-unwind.mir index bda9e9d8e6045..43058051c32ca 100644 --- a/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-unwind.mir @@ -34,7 +34,7 @@ fn option_traits(_1: Option) -> Option { } bb3: { - _0 = as FromResidual>>::from_residual(const Option::::None) -> [return: bb4, unwind continue]; + _0 = as Residual>::into_try_type(const Option::::None) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/ui/try-block/try-block-bad-type.rs b/tests/ui/try-block/try-block-bad-type.rs index 00cd0af127c87..c302496b29b1c 100644 --- a/tests/ui/try-block/try-block-bad-type.rs +++ b/tests/ui/try-block/try-block-bad-type.rs @@ -4,7 +4,7 @@ pub fn main() { let res: Result = try { - Err("")?; //~ ERROR `?` couldn't convert the error + Err("")?; //~ ERROR mismatched types 5 }; diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index cf1cd60a7d5e4..9df01a4cf5b16 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -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>` - | - = 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` is implemented for it - --> $SRC_DIR/core/src/array/mod.rs:LL:COL - = help: for that trait implementation, expected `Infallible`, found `&str` + | ^^^^^^^^ expected `Result`, found `Result<_, &str>` + | + = note: expected enum `Result` + 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 ` 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`.