Skip to content

delegation: add support for wrapping of the return value with From::from - #160433

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
aerooneqq:delegation-return-wrapping-3
Aug 8, 2026
Merged

delegation: add support for wrapping of the return value with From::from#160433
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
aerooneqq:delegation-return-wrapping-3

Conversation

@aerooneqq

@aerooneqq aerooneqq commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

This PR supports wrapping the return value of the delegation with From::from(...) call. This wrapping is applied only if we understand that Self generic param is present in the output of the signature function. The default case are output types such as Rc<Self>, Box<Self>, etc. So given

trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}

As return type of the trait is Box<Self> for the delegation to work we need to wrap the return value in the From::from call.

Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type Box<Box<Self>> , in order to support such chains of types we need to generate several From::from calls: From::<Box<_>>::from(From::from(...)). In such cases there are two problems:

  • First we need to create a heuristic two understand how many From::from calls should be generated, it is easy for pointer types like Box, Arc, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: Struct<Box<Rc<Self>>, Arc<Self>>. This approach is useful for pointer types but it does not cover all cases in general,
  • Next, there will be problems with From generic arg inference, if we comeback to case with Box<Box<Self>> and generate the following from chain: From::from(From::from(...)) we would get an inference error:
    fn f() -> Box<Box<Box<usize>>> {
          Box::from(Box::from(Box::from(1)))
    }
    
    // Error:
    error[E0283]: type annotations needed
     --> src/main.rs:5:9
      |
    5 |         Box::from(Box::from(Box::from(1)))
      |         ^^^ cannot infer type for struct `Box<_, _>`
      |
      = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
              - impl<T> From<T> for Box<T>;
              - impl<T> From<T> for T;
    We need to explicitly specify generics of From trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single From::from call, which supports simple cases like Box<Self>, and if a complex type is used then the user should implement a From trait for it.

Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of From::from call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }.

Part of #118212.
r? @petrochenkov

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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. labels Aug 3, 2026
@rust-log-analyzer

This comment has been minimized.

@aerooneqq
aerooneqq force-pushed the delegation-return-wrapping-3 branch 3 times, most recently from 023c3ee to 981b182 Compare August 4, 2026 06:41
@aerooneqq

Copy link
Copy Markdown
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 4, 2026
@aerooneqq
aerooneqq marked this pull request as ready for review August 4, 2026 06:42
Comment thread compiler/rustc_ast_lowering/src/delegation/resolution.rs
@petrochenkov petrochenkov added the F-fn_delegation `#![feature(fn_delegation)]` label Aug 4, 2026

// Used to fallback `{float}` to `f32` when `f32: From<{float}>`
From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
FromFn, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;

@petrochenkov petrochenkov Aug 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expected this to already be used by AST lowering, but apparently all the operators were migrated to other more specific trait methods like Try::from_residual and similar.

View changes since the review

Comment thread compiler/rustc_ast_lowering/src/delegation/resolution.rs
Comment thread compiler/rustc_ast_lowering/src/delegation/mod.rs Outdated
@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 5, 2026
@aerooneqq
aerooneqq force-pushed the delegation-return-wrapping-3 branch from 3f6a306 to c030ba8 Compare August 6, 2026 06:14
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 6, 2026
@petrochenkov

Copy link
Copy Markdown
Contributor

r=me after squashing commits.
@rustbot author
@bors delegate+

@rust-bors

rust-bors Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

✌️ @aerooneqq, you can now approve this pull request!

If @petrochenkov told you to "r=me" after making some further change, then please make that change and post @bors r=petrochenkov.

View changes since this delegation.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 6, 2026
@rustbot

rustbot commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@aerooneqq

Copy link
Copy Markdown
Contributor Author

@bors squash

@rust-bors

This comment has been minimized.

…from`

* Add support for wrapping of the return value of delegation
* Cleanups
* Review: use `make_lang_item_qpath`
@rust-bors

rust-bors Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🔨 3 commits were squashed into 140d4cb.

@rust-bors
rust-bors Bot force-pushed the delegation-return-wrapping-3 branch from c030ba8 to 140d4cb Compare August 6, 2026 10:56
@aerooneqq

Copy link
Copy Markdown
Contributor Author

@bors r=petrochenkov

@rust-bors

rust-bors Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 140d4cb has been approved by petrochenkov

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 6, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 6, 2026
…ng-3, r=petrochenkov

delegation: add support for wrapping of the return value with `From::from`

This PR supports wrapping the return value of the delegation with `From::from(...)` call. This wrapping is applied only if we understand that `Self` generic param is present in the output of the signature function. The default case are output types such as `Rc<Self>`, `Box<Self>`, etc. So given
```rust
trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}
```

As return type of the trait is `Box<Self>` for the delegation to work we need to wrap the return value in the `From::from` call.

## Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type `Box<Box<Self>>` , in order to support such chains of types we need to generate several `From::from` calls: `From::<Box<_>>::from(From::from(...))`. In such cases there are two problems:

- First we need to create a heuristic two understand how many `From::from` calls should be generated, it is easy for pointer types like `Box`, `Arc`, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: `Struct<Box<Rc<Self>>, Arc<Self>>`. This approach is useful for pointer types but it does not cover all cases in general,
- Next, there will be problems with `From` generic arg inference, if we comeback to case with `Box<Box<Self>>` and generate the following `from` chain: `From::from(From::from(...))` we would get an inference error:
  ```rust
  fn f() -> Box<Box<Box<usize>>> {
        Box::from(Box::from(Box::from(1)))
  }

  // Error:
  error[E0283]: type annotations needed
   --> src/main.rs:5:9
    |
  5 |         Box::from(Box::from(Box::from(1)))
    |         ^^^ cannot infer type for struct `Box<_, _>`
    |
    = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
            - impl<T> From<T> for Box<T>;
            - impl<T> From<T> for T;
  ```
  We need to explicitly specify generics of `From` trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single `From::from` call, which supports simple cases like `Box<Self>`, and if a complex type is used then the user should implement a `From` trait for it.

## Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of `From::from` call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: `reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }`.

Part of rust-lang#118212.
r? @petrochenkov
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 6, 2026
…ng-3, r=petrochenkov

delegation: add support for wrapping of the return value with `From::from`

This PR supports wrapping the return value of the delegation with `From::from(...)` call. This wrapping is applied only if we understand that `Self` generic param is present in the output of the signature function. The default case are output types such as `Rc<Self>`, `Box<Self>`, etc. So given
```rust
trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}
```

As return type of the trait is `Box<Self>` for the delegation to work we need to wrap the return value in the `From::from` call.

## Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type `Box<Box<Self>>` , in order to support such chains of types we need to generate several `From::from` calls: `From::<Box<_>>::from(From::from(...))`. In such cases there are two problems:

- First we need to create a heuristic two understand how many `From::from` calls should be generated, it is easy for pointer types like `Box`, `Arc`, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: `Struct<Box<Rc<Self>>, Arc<Self>>`. This approach is useful for pointer types but it does not cover all cases in general,
- Next, there will be problems with `From` generic arg inference, if we comeback to case with `Box<Box<Self>>` and generate the following `from` chain: `From::from(From::from(...))` we would get an inference error:
  ```rust
  fn f() -> Box<Box<Box<usize>>> {
        Box::from(Box::from(Box::from(1)))
  }

  // Error:
  error[E0283]: type annotations needed
   --> src/main.rs:5:9
    |
  5 |         Box::from(Box::from(Box::from(1)))
    |         ^^^ cannot infer type for struct `Box<_, _>`
    |
    = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
            - impl<T> From<T> for Box<T>;
            - impl<T> From<T> for T;
  ```
  We need to explicitly specify generics of `From` trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single `From::from` call, which supports simple cases like `Box<Self>`, and if a complex type is used then the user should implement a `From` trait for it.

## Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of `From::from` call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: `reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }`.

Part of rust-lang#118212.
r? @petrochenkov
jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 7, 2026
…ng-3, r=petrochenkov

delegation: add support for wrapping of the return value with `From::from`

This PR supports wrapping the return value of the delegation with `From::from(...)` call. This wrapping is applied only if we understand that `Self` generic param is present in the output of the signature function. The default case are output types such as `Rc<Self>`, `Box<Self>`, etc. So given
```rust
trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}
```

As return type of the trait is `Box<Self>` for the delegation to work we need to wrap the return value in the `From::from` call.

## Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type `Box<Box<Self>>` , in order to support such chains of types we need to generate several `From::from` calls: `From::<Box<_>>::from(From::from(...))`. In such cases there are two problems:

- First we need to create a heuristic two understand how many `From::from` calls should be generated, it is easy for pointer types like `Box`, `Arc`, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: `Struct<Box<Rc<Self>>, Arc<Self>>`. This approach is useful for pointer types but it does not cover all cases in general,
- Next, there will be problems with `From` generic arg inference, if we comeback to case with `Box<Box<Self>>` and generate the following `from` chain: `From::from(From::from(...))` we would get an inference error:
  ```rust
  fn f() -> Box<Box<Box<usize>>> {
        Box::from(Box::from(Box::from(1)))
  }

  // Error:
  error[E0283]: type annotations needed
   --> src/main.rs:5:9
    |
  5 |         Box::from(Box::from(Box::from(1)))
    |         ^^^ cannot infer type for struct `Box<_, _>`
    |
    = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
            - impl<T> From<T> for Box<T>;
            - impl<T> From<T> for T;
  ```
  We need to explicitly specify generics of `From` trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single `From::from` call, which supports simple cases like `Box<Self>`, and if a complex type is used then the user should implement a `From` trait for it.

## Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of `From::from` call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: `reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }`.

Part of rust-lang#118212.
r? @petrochenkov
jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 7, 2026
…ng-3, r=petrochenkov

delegation: add support for wrapping of the return value with `From::from`

This PR supports wrapping the return value of the delegation with `From::from(...)` call. This wrapping is applied only if we understand that `Self` generic param is present in the output of the signature function. The default case are output types such as `Rc<Self>`, `Box<Self>`, etc. So given
```rust
trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}
```

As return type of the trait is `Box<Self>` for the delegation to work we need to wrap the return value in the `From::from` call.

## Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type `Box<Box<Self>>` , in order to support such chains of types we need to generate several `From::from` calls: `From::<Box<_>>::from(From::from(...))`. In such cases there are two problems:

- First we need to create a heuristic two understand how many `From::from` calls should be generated, it is easy for pointer types like `Box`, `Arc`, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: `Struct<Box<Rc<Self>>, Arc<Self>>`. This approach is useful for pointer types but it does not cover all cases in general,
- Next, there will be problems with `From` generic arg inference, if we comeback to case with `Box<Box<Self>>` and generate the following `from` chain: `From::from(From::from(...))` we would get an inference error:
  ```rust
  fn f() -> Box<Box<Box<usize>>> {
        Box::from(Box::from(Box::from(1)))
  }

  // Error:
  error[E0283]: type annotations needed
   --> src/main.rs:5:9
    |
  5 |         Box::from(Box::from(Box::from(1)))
    |         ^^^ cannot infer type for struct `Box<_, _>`
    |
    = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
            - impl<T> From<T> for Box<T>;
            - impl<T> From<T> for T;
  ```
  We need to explicitly specify generics of `From` trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single `From::from` call, which supports simple cases like `Box<Self>`, and if a complex type is used then the user should implement a `From` trait for it.

## Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of `From::from` call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: `reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }`.

Part of rust-lang#118212.
r? @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Aug 7, 2026
Rollup of 14 pull requests

Successful merges:

 - #150885 (Revive L4Re target)
 - #159643 (Add support for splatted function pointers)
 - #160433 (delegation: add support for wrapping of the return value with `From::from`)
 - #160530 (refactor handling of target features in Session)
 - #160606 (bootstrap: Store and use an explicit CheckKind in `check::Rustc`)
 - #160628 (fix ICE in `suggest_add_reference_to_arg` for non-callable items)
 - #160634 (miri subtree update)
 - #158904 (Fix FutureDropPoll shim for by-move async closures)
 - #160335 (dlopen offload)
 - #160445 (codegen: classify localized MSVC linker progress as linker_info)
 - #160504 (cleanup borrowck, improve c-variadic handling)
 - #160587 (Add regression test for associated type outlives bound at call site)
 - #160625 (platform-support/netbsd.md: No longer mention 8.x, due to EoL.)
 - #160636 (derive(Diagnostic): link to proper docs)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 7, 2026
…ng-3, r=petrochenkov

delegation: add support for wrapping of the return value with `From::from`

This PR supports wrapping the return value of the delegation with `From::from(...)` call. This wrapping is applied only if we understand that `Self` generic param is present in the output of the signature function. The default case are output types such as `Rc<Self>`, `Box<Self>`, etc. So given
```rust
trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}
```

As return type of the trait is `Box<Self>` for the delegation to work we need to wrap the return value in the `From::from` call.

## Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type `Box<Box<Self>>` , in order to support such chains of types we need to generate several `From::from` calls: `From::<Box<_>>::from(From::from(...))`. In such cases there are two problems:

- First we need to create a heuristic two understand how many `From::from` calls should be generated, it is easy for pointer types like `Box`, `Arc`, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: `Struct<Box<Rc<Self>>, Arc<Self>>`. This approach is useful for pointer types but it does not cover all cases in general,
- Next, there will be problems with `From` generic arg inference, if we comeback to case with `Box<Box<Self>>` and generate the following `from` chain: `From::from(From::from(...))` we would get an inference error:
  ```rust
  fn f() -> Box<Box<Box<usize>>> {
        Box::from(Box::from(Box::from(1)))
  }

  // Error:
  error[E0283]: type annotations needed
   --> src/main.rs:5:9
    |
  5 |         Box::from(Box::from(Box::from(1)))
    |         ^^^ cannot infer type for struct `Box<_, _>`
    |
    = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
            - impl<T> From<T> for Box<T>;
            - impl<T> From<T> for T;
  ```
  We need to explicitly specify generics of `From` trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single `From::from` call, which supports simple cases like `Box<Self>`, and if a complex type is used then the user should implement a `From` trait for it.

## Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of `From::from` call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: `reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }`.

Part of rust-lang#118212.
r? @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Aug 7, 2026
…uwer

Rollup of 21 pull requests

Successful merges:

 - #159784 (Hint that memchr returns an in-bounds index)
 - #150885 (Revive L4Re target)
 - #159643 (Add support for splatted function pointers)
 - #160433 (delegation: add support for wrapping of the return value with `From::from`)
 - #160530 (refactor handling of target features in Session)
 - #160606 (bootstrap: Store and use an explicit CheckKind in `check::Rustc`)
 - #160628 (fix ICE in `suggest_add_reference_to_arg` for non-callable items)
 - #160634 (miri subtree update)
 - #157641 (Do not promote extern statics)
 - #158904 (Fix FutureDropPoll shim for by-move async closures)
 - #160103 (Add regression test for GAT bound mismatched type error)
 - #160335 (dlopen offload)
 - #160445 (codegen: classify localized MSVC linker progress as linker_info)
 - #160499 (rustc_resolve: move diagnostic attribute linting to attr parsing)
 - #160504 (cleanup borrowck, improve c-variadic handling)
 - #160577 (expand: Feature gate AST-based attribute macros on expressions and statements)
 - #160587 (Add regression test for associated type outlives bound at call site)
 - #160625 (platform-support/netbsd.md: No longer mention 8.x, due to EoL.)
 - #160636 (derive(Diagnostic): link to proper docs)
 - #160644 (Clean up some manual debug impls)
 - #160649 (move naked function ui tests)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 7, 2026
…ng-3, r=petrochenkov

delegation: add support for wrapping of the return value with `From::from`

This PR supports wrapping the return value of the delegation with `From::from(...)` call. This wrapping is applied only if we understand that `Self` generic param is present in the output of the signature function. The default case are output types such as `Rc<Self>`, `Box<Self>`, etc. So given
```rust
trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}
```

As return type of the trait is `Box<Self>` for the delegation to work we need to wrap the return value in the `From::from` call.

## Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type `Box<Box<Self>>` , in order to support such chains of types we need to generate several `From::from` calls: `From::<Box<_>>::from(From::from(...))`. In such cases there are two problems:

- First we need to create a heuristic two understand how many `From::from` calls should be generated, it is easy for pointer types like `Box`, `Arc`, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: `Struct<Box<Rc<Self>>, Arc<Self>>`. This approach is useful for pointer types but it does not cover all cases in general,
- Next, there will be problems with `From` generic arg inference, if we comeback to case with `Box<Box<Self>>` and generate the following `from` chain: `From::from(From::from(...))` we would get an inference error:
  ```rust
  fn f() -> Box<Box<Box<usize>>> {
        Box::from(Box::from(Box::from(1)))
  }

  // Error:
  error[E0283]: type annotations needed
   --> src/main.rs:5:9
    |
  5 |         Box::from(Box::from(Box::from(1)))
    |         ^^^ cannot infer type for struct `Box<_, _>`
    |
    = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
            - impl<T> From<T> for Box<T>;
            - impl<T> From<T> for T;
  ```
  We need to explicitly specify generics of `From` trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single `From::from` call, which supports simple cases like `Box<Self>`, and if a complex type is used then the user should implement a `From` trait for it.

## Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of `From::from` call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: `reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }`.

Part of rust-lang#118212.
r? @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Aug 7, 2026
…uwer

Rollup of 20 pull requests

Successful merges:

 - #159784 (Hint that memchr returns an in-bounds index)
 - #150885 (Revive L4Re target)
 - #159643 (Add support for splatted function pointers)
 - #160433 (delegation: add support for wrapping of the return value with `From::from`)
 - #160530 (refactor handling of target features in Session)
 - #160606 (bootstrap: Store and use an explicit CheckKind in `check::Rustc`)
 - #160628 (fix ICE in `suggest_add_reference_to_arg` for non-callable items)
 - #160634 (miri subtree update)
 - #157641 (Do not promote extern statics)
 - #158904 (Fix FutureDropPoll shim for by-move async closures)
 - #160103 (Add regression test for GAT bound mismatched type error)
 - #160335 (dlopen offload)
 - #160445 (codegen: classify localized MSVC linker progress as linker_info)
 - #160499 (rustc_resolve: move diagnostic attribute linting to attr parsing)
 - #160504 (cleanup borrowck, improve c-variadic handling)
 - #160577 (expand: Feature gate AST-based attribute macros on expressions and statements)
 - #160587 (Add regression test for associated type outlives bound at call site)
 - #160625 (platform-support/netbsd.md: No longer mention 8.x, due to EoL.)
 - #160636 (derive(Diagnostic): link to proper docs)
 - #160644 (Clean up some manual debug impls)
jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 7, 2026
…ng-3, r=petrochenkov

delegation: add support for wrapping of the return value with `From::from`

This PR supports wrapping the return value of the delegation with `From::from(...)` call. This wrapping is applied only if we understand that `Self` generic param is present in the output of the signature function. The default case are output types such as `Rc<Self>`, `Box<Self>`, etc. So given
```rust
trait MyAdd {
    fn add(self, other: Self) -> Box<Self>;
}

impl MyAdd for usize {
    fn add(self, other: usize) -> Box<usize> {
        Box::new(self + other)
    }
}

#[derive(Eq, PartialEq, Debug)]
struct W(Box<usize>);

reuse impl MyAdd for W { *self.0 }

// Desugaring:
#[attr = Inline(Hint)]
fn add(self: _, arg1: _) ->_ {
    From::from(Self { 0: MyAdd::add(*self.0, *self.0) })
}
```

As return type of the trait is `Box<Self>` for the delegation to work we need to wrap the return value in the `From::from` call.

## Many from calls

Now only single from is generated which limits the number of supported cases. Consider the return type `Box<Box<Self>>` , in order to support such chains of types we need to generate several `From::from` calls: `From::<Box<_>>::from(From::from(...))`. In such cases there are two problems:

- First we need to create a heuristic two understand how many `From::from` calls should be generated, it is easy for pointer types like `Box`, `Arc`, etc., however if custom types with complex type trees will be considered, the choice is not that obvious: `Struct<Box<Rc<Self>>, Arc<Self>>`. This approach is useful for pointer types but it does not cover all cases in general,
- Next, there will be problems with `From` generic arg inference, if we comeback to case with `Box<Box<Self>>` and generate the following `from` chain: `From::from(From::from(...))` we would get an inference error:
  ```rust
  fn f() -> Box<Box<Box<usize>>> {
        Box::from(Box::from(Box::from(1)))
  }

  // Error:
  error[E0283]: type annotations needed
   --> src/main.rs:5:9
    |
  5 |         Box::from(Box::from(Box::from(1)))
    |         ^^^ cannot infer type for struct `Box<_, _>`
    |
    = note: multiple `impl`s satisfying `Box<Box<Box<usize>>>: From<Box<_, _>>` found in the following crates: `alloc`, `core`:
            - impl<T> From<T> for Box<T>;
            - impl<T> From<T> for T;
  ```
  We need to explicitly specify generics of `From` trait for this to work, and if we have non-trivial type trees it is not obvious whose generics to specify, in case of chains of pointers it is easy, but in general it is not trivial.

Given those concerns for now we generate a single `From::from` call, which supports simple cases like `Box<Self>`, and if a complex type is used then the user should implement a `From` trait for it.

## Alternative designs

As an alternative we can create any kind of marker that can be used to mark the function that should be used for output type conversion instead of `From::from` call. However this will implicitly grow delegation's syntax budget because it is equivalent to specifying output conversion explicitly: `reuse Trait::foo { self.0 } { MyStruct::delegation_from(self) }`.

Part of rust-lang#118212.
r? @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Aug 7, 2026
…uwer

Rollup of 28 pull requests

Successful merges:

 - #159784 (Hint that memchr returns an in-bounds index)
 - #160673 (Improve `canonical_param_env_cache`)
 - #150885 (Revive L4Re target)
 - #159643 (Add support for splatted function pointers)
 - #160433 (delegation: add support for wrapping of the return value with `From::from`)
 - #160530 (refactor handling of target features in Session)
 - #160606 (bootstrap: Store and use an explicit CheckKind in `check::Rustc`)
 - #160628 (fix ICE in `suggest_add_reference_to_arg` for non-callable items)
 - #160683 (Add regression test for unknown feaeture name reported with other errors)
 - #157641 (Do not promote extern statics)
 - #158904 (Fix FutureDropPoll shim for by-move async closures)
 - #159816 (added note/help about iterator invalidation when mutating a collection inside a for loop)
 - #160103 (Add regression test for GAT bound mismatched type error)
 - #160335 (dlopen offload)
 - #160445 (codegen: classify localized MSVC linker progress as linker_info)
 - #160499 (rustc_resolve: move diagnostic attribute linting to attr parsing)
 - #160504 (cleanup borrowck, improve c-variadic handling)
 - #160577 (expand: Feature gate AST-based attribute macros on expressions and statements)
 - #160587 (Add regression test for associated type outlives bound at call site)
 - #160625 (platform-support/netbsd.md: No longer mention 8.x, due to EoL.)
 - #160633 (delegation: fix determining wrong `FnKind` when delegation is inside const arg)
 - #160636 (derive(Diagnostic): link to proper docs)
 - #160644 (Clean up some manual debug impls)
 - #160649 (move naked function ui tests)
 - #160672 (Improve `MaybeLiveLocals`)
 - #160693 (Add branch config for perf. unrolling in bors)
 - #160696 (rustc_codegen_llvm: handle sm_101* features being an alias)
 - #160706 (renovate: clarify that vulnerability PRs are opened automatically)
@rust-bors
rust-bors Bot merged commit f6d93ec into rust-lang:main Aug 8, 2026
13 checks passed
@rustbot rustbot added this to the 1.99.0 milestone Aug 8, 2026
pull Bot pushed a commit to LeeeeeeM/miri that referenced this pull request Aug 8, 2026
…uwer

Rollup of 28 pull requests

Successful merges:

 - rust-lang/rust#159784 (Hint that memchr returns an in-bounds index)
 - rust-lang/rust#160673 (Improve `canonical_param_env_cache`)
 - rust-lang/rust#150885 (Revive L4Re target)
 - rust-lang/rust#159643 (Add support for splatted function pointers)
 - rust-lang/rust#160433 (delegation: add support for wrapping of the return value with `From::from`)
 - rust-lang/rust#160530 (refactor handling of target features in Session)
 - rust-lang/rust#160606 (bootstrap: Store and use an explicit CheckKind in `check::Rustc`)
 - rust-lang/rust#160628 (fix ICE in `suggest_add_reference_to_arg` for non-callable items)
 - rust-lang/rust#160683 (Add regression test for unknown feaeture name reported with other errors)
 - rust-lang/rust#157641 (Do not promote extern statics)
 - rust-lang/rust#158904 (Fix FutureDropPoll shim for by-move async closures)
 - rust-lang/rust#159816 (added note/help about iterator invalidation when mutating a collection inside a for loop)
 - rust-lang/rust#160103 (Add regression test for GAT bound mismatched type error)
 - rust-lang/rust#160335 (dlopen offload)
 - rust-lang/rust#160445 (codegen: classify localized MSVC linker progress as linker_info)
 - rust-lang/rust#160499 (rustc_resolve: move diagnostic attribute linting to attr parsing)
 - rust-lang/rust#160504 (cleanup borrowck, improve c-variadic handling)
 - rust-lang/rust#160577 (expand: Feature gate AST-based attribute macros on expressions and statements)
 - rust-lang/rust#160587 (Add regression test for associated type outlives bound at call site)
 - rust-lang/rust#160625 (platform-support/netbsd.md: No longer mention 8.x, due to EoL.)
 - rust-lang/rust#160633 (delegation: fix determining wrong `FnKind` when delegation is inside const arg)
 - rust-lang/rust#160636 (derive(Diagnostic): link to proper docs)
 - rust-lang/rust#160644 (Clean up some manual debug impls)
 - rust-lang/rust#160649 (move naked function ui tests)
 - rust-lang/rust#160672 (Improve `MaybeLiveLocals`)
 - rust-lang/rust#160693 (Add branch config for perf. unrolling in bors)
 - rust-lang/rust#160696 (rustc_codegen_llvm: handle sm_101* features being an alias)
 - rust-lang/rust#160706 (renovate: clarify that vulnerability PRs are opened automatically)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-fn_delegation `#![feature(fn_delegation)]` S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants