Skip to content

Commit 112edf6

Browse files
authored
Unrolled build for #148725
Rollup merge of #148725 - scottmcm:experiment-new-try-block-v3, r=petrochenkov Implement the alternative `try` block desugaring As discussed in rust-lang/rfcs#3721 (comment), update the `try` in nightly to match the RFC as a way to experiment. This addresses the following unresolved issue from #31436 > Address issues with type inference (`try { expr? }?` currently requires an explicit type annotation somewhere).
2 parents c880acd + e5803fc commit 112edf6

File tree

11 files changed

+82
-22
lines changed

11 files changed

+82
-22
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
19291929
/// ControlFlow::Break(residual) =>
19301930
/// #[allow(unreachable_code)]
19311931
/// // If there is an enclosing `try {...}`:
1932-
/// break 'catch_target Try::from_residual(residual),
1932+
/// break 'catch_target Residual::into_try_type(residual),
19331933
/// // Otherwise:
19341934
/// return Try::from_residual(residual),
19351935
/// }
@@ -1979,7 +1979,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
19791979
let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
19801980
let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
19811981
let from_residual_expr = self.wrap_in_try_constructor(
1982-
hir::LangItem::TryTraitFromResidual,
1982+
if self.catch_scope.is_some() {
1983+
hir::LangItem::ResidualIntoTryType
1984+
} else {
1985+
hir::LangItem::TryTraitFromResidual
1986+
},
19831987
try_span,
19841988
self.arena.alloc(residual_expr),
19851989
unstable_span,

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
183183
impl_trait_defs: Vec::new(),
184184
impl_trait_bounds: Vec::new(),
185185
allow_contracts: [sym::contracts_internals].into(),
186-
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
186+
allow_try_trait: [
187+
sym::try_trait_v2,
188+
sym::try_trait_v2_residual,
189+
sym::yeet_desugar_details,
190+
]
191+
.into(),
187192
allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),
188193
allow_gen_future: if tcx.features().async_fn_track_caller() {
189194
[sym::gen_future, sym::closure_track_caller].into()

compiler/rustc_hir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ language_item_table! {
370370
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
371371
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
372372
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
373+
ResidualIntoTryType, sym::into_try_type, into_try_type_fn, Target::Fn, GenericRequirement::None;
373374

374375
CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait, GenericRequirement::Exact(0);
375376

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,7 @@ symbols! {
12591259
into_async_iter_into_iter,
12601260
into_future,
12611261
into_iter,
1262+
into_try_type,
12621263
intra_doc_pointers,
12631264
intrinsics,
12641265
intrinsics_unaligned_volatile_load,
@@ -2280,6 +2281,7 @@ symbols! {
22802281
try_from_fn,
22812282
try_into,
22822283
try_trait_v2,
2284+
try_trait_v2_residual,
22832285
try_update,
22842286
tt,
22852287
tuple,

library/core/src/ops/try_trait.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,24 @@ where
359359
/// and in the other direction,
360360
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
361361
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
362-
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
363-
pub const trait Residual<O> {
362+
#[rustc_const_unstable(feature = "const_try_residual", issue = "91285")]
363+
pub const trait Residual<O>: Sized {
364364
/// The "return" type of this meta-function.
365365
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
366-
type TryType: Try<Output = O, Residual = Self>;
366+
type TryType: [const] Try<Output = O, Residual = Self>;
367+
}
368+
369+
/// Used in `try {}` blocks so the type produced in the `?` desugaring
370+
/// depends on the residual type `R` and the output type of the block `O`,
371+
/// but importantly not on the contextual type the way it would be if
372+
/// we called `<_ as FromResidual>::from_residual(r)` directly.
373+
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
374+
// needs to be `pub` to avoid `private type` errors
375+
#[expect(unreachable_pub)]
376+
#[inline] // FIXME: force would be nice, but fails -- see #148915
377+
#[lang = "into_try_type"]
378+
pub fn residual_into_try_type<R: Residual<O>, O>(r: R) -> <R as Residual<O>>::TryType {
379+
FromResidual::from_residual(r)
367380
}
368381

369382
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]

library/std/src/sys/pal/unix/kernel_copy/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn copy_specialization() -> Result<()> {
5050
"inner Take allowed reading beyond end of file, some bytes should be left"
5151
);
5252

53-
let mut sink = sink.into_inner()?;
53+
let mut sink = sink.into_inner().map_err(io::Error::from)?;
5454
sink.seek(SeekFrom::Start(0))?;
5555
let mut copied = Vec::new();
5656
sink.read_to_end(&mut copied)?;

tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-abort.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn option_traits(_1: Option<u32>) -> Option<u32> {
3434
}
3535

3636
bb3: {
37-
_0 = <Option<u32> as FromResidual<Option<Infallible>>>::from_residual(const Option::<Infallible>::None) -> [return: bb4, unwind unreachable];
37+
_0 = ops::try_trait::residual_into_try_type::<Option<Infallible>, u32>(const Option::<Infallible>::None) -> [return: bb4, unwind unreachable];
3838
}
3939

4040
bb4: {

tests/mir-opt/pre-codegen/option_bubble_debug.option_traits.PreCodegen.after.panic-unwind.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn option_traits(_1: Option<u32>) -> Option<u32> {
3434
}
3535

3636
bb3: {
37-
_0 = <Option<u32> as FromResidual<Option<Infallible>>>::from_residual(const Option::<Infallible>::None) -> [return: bb4, unwind continue];
37+
_0 = ops::try_trait::residual_into_try_type::<Option<Infallible>, u32>(const Option::<Infallible>::None) -> [return: bb4, unwind continue];
3838
}
3939

4040
bb4: {

tests/ui/try-block/try-block-bad-type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
pub fn main() {
66
let res: Result<u32, std::array::TryFromSliceError> = try {
7-
Err("")?; //~ ERROR `?` couldn't convert the error
7+
Err("")?; //~ ERROR mismatched types
88
5
99
};
1010

tests/ui/try-block/try-block-bad-type.stderr

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
error[E0277]: `?` couldn't convert the error to `TryFromSliceError`
2-
--> $DIR/try-block-bad-type.rs:7:16
1+
error[E0308]: mismatched types
2+
--> $DIR/try-block-bad-type.rs:7:9
33
|
44
LL | Err("")?;
5-
| -------^ the trait `From<&str>` is not implemented for `TryFromSliceError`
6-
| |
7-
| this can't be annotated with `?` because it has type `Result<_, &str>`
8-
|
9-
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
10-
help: the trait `From<&str>` is not implemented for `TryFromSliceError`
11-
but trait `From<Infallible>` is implemented for it
12-
--> $SRC_DIR/core/src/array/mod.rs:LL:COL
13-
= help: for that trait implementation, expected `Infallible`, found `&str`
5+
| ^^^^^^^^ expected `Result<u32, TryFromSliceError>`, found `Result<_, &str>`
6+
|
7+
= note: expected enum `Result<u32, TryFromSliceError>`
8+
found enum `Result<_, &str>`
9+
help: consider using `Result::expect` to unwrap the `Result<_, &str>` value, panicking if the value is a `Result::Err`
10+
|
11+
LL | Err("")?.expect("REASON");
12+
| +++++++++++++++++
1413

1514
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
1615
--> $DIR/try-block-bad-type.rs:12:9
@@ -42,5 +41,5 @@ LL | let res: i32 = try { 5 };
4241

4342
error: aborting due to 5 previous errors
4443

45-
Some errors have detailed explanations: E0271, E0277.
44+
Some errors have detailed explanations: E0271, E0277, E0308.
4645
For more information about an error, try `rustc --explain E0271`.

0 commit comments

Comments
 (0)