Auto merge of #125929 - Bryanskiy:delegation-generics-3, r=petrochenkov
Delegation: support generics for delegation from free functions (The PR was split from https://github.com/rust-lang/rust/pull/123958, explainer - https://github.com/Bryanskiy/posts/blob/master/delegation%20in%20generic%20contexts.md) This PR implements generics inheritance from free functions to free functions and trait methods. #### free functions to free functions: ```rust fn to_reuse<T: Clone>(_: T) {} reuse to_reuse as bar; // desugaring: fn bar<T: Clone>(x: T) { to_reuse(x) } ``` Generics, predicates and signature are simply copied. Generic arguments in paths are ignored during generics inheritance: ```rust fn to_reuse<T: Clone>(_: T) {} reuse to_reuse::<u8> as bar; // desugaring: fn bar<T: Clone>(x: T) { to_reuse::<u8>(x) // ERROR: mismatched types } ``` Due to implementation limitations callee path is lowered without modifications. Therefore, it is a compilation error at the moment. #### free functions to trait methods: ```rust trait Trait<'a, A> { fn foo<'b, B>(&self, x: A, y: B) {...} } reuse Trait::foo; // desugaring: fn foo<'a, 'b, This: Trait<'a, A>, A, B>(this: &This, x: A, y: B) { Trait::foo(this, x, y) } ``` The inheritance is similar to the previous case but with some corrections: - `Self` parameter converted into `T: Trait` - generic parameters need to be reordered so that lifetimes go first Arguments are similarly ignored. --- In the future, we plan to support generic inheritance for delegating from all contexts to all contexts (from free/trait/impl to free/trait /impl). These cases were considered first as the simplest from the implementation perspective.
This commit is contained in:
commit
1ddedbaa59
24 changed files with 702 additions and 233 deletions
|
@ -746,6 +746,21 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
|
||||
if let Some(ret) = self.get_fn_output(def_id)
|
||||
&& let FnRetTy::Return(ty) = ret
|
||||
&& let TyKind::InferDelegation(sig_id, _) = ty.kind
|
||||
{
|
||||
return Some(sig_id);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn delegation_sig_id(self, def_id: LocalDefId) -> DefId {
|
||||
self.opt_delegation_sig_id(def_id).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn opt_ident(self, id: HirId) -> Option<Ident> {
|
||||
match self.tcx.hir_node(id) {
|
||||
|
|
|
@ -1722,6 +1722,10 @@ rustc_queries! {
|
|||
desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
|
||||
}
|
||||
|
||||
query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] {
|
||||
desc { "inheriting delegation signature" }
|
||||
}
|
||||
|
||||
/// Does lifetime resolution on items. Importantly, we can't resolve
|
||||
/// lifetimes directly on things like trait methods, because of trait params.
|
||||
/// See `rustc_resolve::late::lifetimes` for details.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue