Skip to content

split try trait in twain#154715

Open
bend-n wants to merge 3 commits into
rust-lang:mainfrom
bend-n:the-try.-split-it
Open

split try trait in twain#154715
bend-n wants to merge 3 commits into
rust-lang:mainfrom
bend-n:the-try.-split-it

Conversation

@bend-n
Copy link
Copy Markdown
Contributor

@bend-n bend-n commented Apr 2, 2026

View all comments

https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/on.20.60Try.60.20for.20.60.26Option.60/with/582974682

currently Try for &Option is impossible, because from_output would need to return &Option from &Self::Output. but i think there should be some way to do Option::as_ref in a generic setting, and i think this is a good cause to split the traits up a bit, like so:

pub trait Branch {
    type Output;
    type Residual;
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}
pub trait FromOutput<O = <Self as Branch>::Output>: Branch {
    fn from_output(output: O) -> Self;
}
pub trait FromResidual<R = <Self as Branch>::Residual>: Branch {
    fn from_residual(residual: R) -> Self;
}
pub trait Try = Branch + FromResidual + FromOutput;
pub trait Residual<O>: Sized {
    type TryType: Try<Output = O, Residual = Self>;
}

which then allows (this is not implemented in this PR.)

impl<'a, T, E> Branch for &'a Result<T, E> {
    type Output = &'a T;
    type Residual = Result<Infallible, &'a E>;

    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {}
}

which then allows

fn as_ref<R>(x: R) -> <R::Residual as Residual<<R as Branch>::Output>>::TryType
where
    R: Branch<Residual: Residual<<R as Branch>::Output>>
 {}

which then allows

let x: Result<&i32, &()> = as_ref(&Ok::<i32, ()>(1));

which i think is a great boon to Try.

@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue. labels Apr 4, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@bend-n bend-n force-pushed the the-try.-split-it branch from 709df2d to cb71243 Compare April 18, 2026 16:37
@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added the T-clippy Relevant to the Clippy team. label Apr 19, 2026
@bend-n bend-n marked this pull request as ready for review April 19, 2026 14:11
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 19, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 19, 2026

rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead.

cc @rust-lang/rust-analyzer

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 19, 2026

r? @jhpratt

rustbot has assigned @jhpratt.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @scottmcm, libs
  • @scottmcm, libs expanded to 7 candidates
  • Random selection from Mark-Simulacrum, jhpratt

Comment thread src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
@jhpratt
Copy link
Copy Markdown
Member

jhpratt commented Apr 21, 2026

@rustbot reroll

@rustbot rustbot assigned scottmcm and unassigned jhpratt Apr 21, 2026
@rust-bors

This comment has been minimized.

@bend-n bend-n force-pushed the the-try.-split-it branch from 9e7b895 to 7491a82 Compare May 6, 2026 11:07
@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@bend-n bend-n force-pushed the the-try.-split-it branch from 7491a82 to 57073d2 Compare May 25, 2026 15:56
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 25, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@bend-n
Copy link
Copy Markdown
Contributor Author

bend-n commented May 25, 2026

@rustbot reroll

@rustbot rustbot assigned Mark-Simulacrum and unassigned scottmcm May 25, 2026
@rust-log-analyzer

This comment has been minimized.

@bend-n bend-n force-pushed the the-try.-split-it branch from 57073d2 to 368771f Compare May 25, 2026 16:37
@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
28    |
29 LL |     let res: () = try { };
30    |                         ^ could not wrap the final value of the block as `()` doesn't implement `Try`
+    |
+    = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `()`
31 
32 error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
33   --> $DIR/try-block-bad-type.rs:17:25

42    |
---
To only update this specific test, also pass `--test-args try-block/try-block-bad-type.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/try-block/try-block-bad-type.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/try-block/try-block-bad-type" "-A" "unused" "-W" "unused_attributes" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2018"
stdout: none
--- stderr -------------------------------
error[E0308]: mismatched types
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type.rs:7:9
   |
LL |         Err("")?; //~ ERROR mismatched types
   |         ^^^^^^^^ expected `Result<u32, TryFromSliceError>`, found `Result<_, &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 mismatched types
   |                 +++++++++++++++++

error[E0271]: type mismatch resolving `<Result<i32, i32> as Branch>::Output == &str`
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type.rs:12:9
   |
LL |         "" //~ ERROR type mismatch
   |         ^^ expected `&str`, found `i32`

error[E0271]: type mismatch resolving `<Result<i32, i32> as Branch>::Output == ()`
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type.rs:15:39
   |
LL |     let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
   |                                       ^ expected `()`, found `i32`

error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type.rs:17:25
   |
LL |     let res: () = try { };
   |                         ^ could not wrap the final value of the block as `()` doesn't implement `Try`
   |
   = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `()`

error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type.rs:17:25
   |
LL |     let res: () = try { };
   |                         ^ could not wrap the final value of the block as `()` doesn't implement `Try`
   |
   = help: the nightly-only, unstable trait `Branch` is not implemented for `()`

error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type.rs:21:26
   |
LL |     let res: i32 = try { 5 }; //~ ERROR a `try` block must return `Result` or `Option`
   |                          ^ could not wrap the final value of the block as `i32` doesn't implement `Try`
   |
   = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `i32`

error: aborting due to 6 previous errors

---
29    |
30 LL |     let res = try bikeshed () { };
31    |                                 ^ could not wrap the final value of the block as `()` doesn't implement `Try`
+    |
+    = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `()`
32 
33 error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
34   --> $DIR/try-block-bad-type-heterogeneous.rs:17:33

43    |
---
To only update this specific test, also pass `--test-args try-block/try-block-bad-type-heterogeneous.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/try-block/try-block-bad-type-heterogeneous.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/try-block/try-block-bad-type-heterogeneous" "-A" "unused" "-W" "unused_attributes" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2018"
stdout: none
--- stderr -------------------------------
error[E0277]: `?` couldn't convert the error to `TryFromSliceError`
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type-heterogeneous.rs:7:16
   |
LL |         Err("")?; //~ ERROR `?` couldn't convert the error
   |         -------^ 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<Infallible>` is implemented for it
  --> /rustc/FAKE_PREFIX/library/core/src/array/mod.rs:198:0
   = help: for that trait implementation, expected `Infallible`, found `&str`

error[E0271]: type mismatch resolving `<Result<i32, i32> as Branch>::Output == &str`
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type-heterogeneous.rs:12:9
   |
LL |         "" //~ ERROR type mismatch
   |         ^^ expected `&str`, found `i32`

error[E0271]: type mismatch resolving `<Result<i32, i32> as Branch>::Output == ()`
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type-heterogeneous.rs:15:47
   |
LL |     let res = try bikeshed Result<i32, i32> { }; //~ ERROR type mismatch
   |                                               ^ expected `()`, found `i32`

error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type-heterogeneous.rs:17:33
   |
LL |     let res = try bikeshed () { };
   |                                 ^ could not wrap the final value of the block as `()` doesn't implement `Try`
   |
   = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `()`

error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type-heterogeneous.rs:17:33
   |
LL |     let res = try bikeshed () { };
   |                                 ^ could not wrap the final value of the block as `()` doesn't implement `Try`
   |
   = help: the nightly-only, unstable trait `Branch` is not implemented for `()`

error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
##[error]  --> /checkout/tests/ui/try-block/try-block-bad-type-heterogeneous.rs:21:34
   |
LL |     let res = try bikeshed i32 { 5 }; //~ ERROR a `try` block must return `Result` or `Option`
   |                                  ^ could not wrap the final value of the block as `i32` doesn't implement `Try`
   |
   = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `i32`

error: aborting due to 6 previous errors

---
Saved the actual stderr to `/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/try-block/try-block-in-while/try-block-in-while.stderr`
diff of stderr:

3    |
4 LL |     while try { false } {}
5    |                 ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try`
+    |
+    = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `bool`
6 
7 error: aborting due to 1 previous error
8 
---
To only update this specific test, also pass `--test-args try-block/try-block-in-while.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/try-block/try-block-in-while.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/try-block/try-block-in-while" "-A" "unused" "-W" "unused_attributes" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2018"
stdout: none
--- stderr -------------------------------
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
##[error]  --> /checkout/tests/ui/try-block/try-block-in-while.rs:6:17
   |
LL |     while try { false } {}
   |                 ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try`
   |
   = help: the nightly-only, unstable trait `FromOutput<_>` is not implemented for `bool`

error: aborting due to 1 previous error

@Mark-Simulacrum Mark-Simulacrum added the I-libs-nominated Nominated for discussion during a libs team meeting. label May 31, 2026
@Mark-Simulacrum
Copy link
Copy Markdown
Member

I know there has been a bunch of discussion about improvements to Try (e.g., something about GATs making the API friendlier), but it's not obvious to me that we want to try to further generalize it. I think it would make sense for T-libs to discuss this and figure out what the right path forward is before we spend more time on review / iteration on the specifics of the PR.

cc @scottmcm @Amanieu

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 31, 2026

☔ The latest upstream changes (presumably #157208) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

I-libs-nominated Nominated for discussion during a libs team meeting. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants