Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate delegate impl #14386

Closed
Veykril opened this issue Mar 21, 2023 · 7 comments · Fixed by #14948
Closed

Generate delegate impl #14386

Veykril opened this issue Mar 21, 2023 · 7 comments · Fixed by #14948
Assignees
Labels
A-assists C-feature Category: feature request E-unknown It's unclear if the issue is E-hard or E-easy without digging in

Comments

@Veykril
Copy link
Member

Veykril commented Mar 21, 2023

We currently have an assist to generate a delegate method for a field and an assist to generate a deref implementation towards a field. I believe we can generalize the latter by generating a "delegated trait impl" to a field, which would include generating a deref impl for a field but also other things like Intoiterator etc

$0 marks the cursor

pub(crate) struct RibStack<R> {
    $0ribs: Vec<R>,
    used: usize,
}

Should offer delegating traits impls implemented by Vec<R>, resulting in output like the following:

impl<R> std::ops::Deref for RibStack<R> {
    type Target = <Vec<R> as std::ops::Deref>::Target;

    fn deref(&self) -> &Self::Target {
        &self.ribs // note that for deref we should special case emitting `&self.field` instead of `self.field.deref()`/`Deref::deref(&self.field)`
    }
}

impl<R> std::ops::DerefMut for RibStack<R> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.ribs // note that for deref we should special case emitting `&mut self.field` instead of `self.field.deref_mut()`/`DerefMut::deref_mut(&mut self.field)`
    }
}

impl<R> IntoIterator for RibStack<R> {
    type Item = <Vec<R> as IntoIterator>::Item;
    type IntoIter = <Vec<R> as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        IntoIterator::into_iter(self.ribs)
    }
}
@Veykril Veykril added A-assists C-feature Category: feature request E-unknown It's unclear if the issue is E-hard or E-easy without digging in labels Mar 21, 2023
@alibektas
Copy link
Member

@rustbot claim

@alibektas
Copy link
Member

alibektas commented Apr 16, 2023

I am trying to obtain generic parameters from a trait definition. For that I implemented hir::Trait:type_or_const_param_collect() that fetches the said infos by cloning.

My first question is if it is really necessary to implement a new method? Another huge downside of doing that is that we need to move this line here which is discouraged !

My second question is how I can get from hir::TypeOrConstParam::TypeParamData to ast::TypeParam as in

let gens: Vec<hir::TypeOrConstParamData> = its_trait.type_or_const_param_collect(db);

for g in gens {
    match g {
        hir::TypeOrConstParamData::TypeParamData(tp) => {
            /// Into **not** implemented. But I need to make a conversion between
            let ast_cpart: ast::TypeParam = tp.into();
        }
        hir::TypeOrConstParamData::ConstParamData(cp) => todo!(),
    }
}

The reason why I am trying to do so it to rely on syntax::ast to create the delegate trait implementations.
I am very much open to new ideas.

@Veykril
Copy link
Member Author

Veykril commented Apr 16, 2023

hir already exposes TypeParam and ConstParam, so your type_or_const_param_collect function should return those instead of the TypeParamData and ConstParamData. Those two should also work with Semantics::to_def to get their source. Second, I think you might be easier off afterall to skip going through the hir in these cases, and instead just copy the syntax nodes where needed for the parameters.

bors added a commit that referenced this issue Apr 21, 2023
Simple fix for make::impl_trait

This is my first PR in this project. I made this PR because I needed this function to work properly for the main PR I am working on  (#14386). This is a small amendment to what it was before. We still need to improve this in order for it to fully comply with its syntactic definition as  stated [here](https://doc.rust-lang.org/reference/items/implementations.html).
@alibektas
Copy link
Member

I wanted to ask what the expectations are in terms of AssocItem::MacroCall coverage . Should I skip handling them for now or is there a resource that I can refer to to make my work with them easier ?

@Veykril
Copy link
Member Author

Veykril commented Apr 23, 2023

Skip them for now, they can be handled afterwards

@alibektas
Copy link
Member

alibektas commented Apr 23, 2023

I was given the following test case

trait Trait<'a, T, const C: usize> {
    type AssocType;
    const AssocConst: usize;
    fn assoc_fn(p: ());
    fn assoc_method(&self, p: ());
}

struct Base;
struct S {
    field: Base
}

impl<'a, T, const C: usize> Trait<'a, T, C> for Base {
    type AssocType = ();
    const AssocConst: usize = 0;
    fn assoc_fn(p: ()) {}
    fn assoc_method(&self, p: ()) {}
}
impl<'a, T, const C: usize> Trait<'a, T, C> for S {
    type AssocType =  <Base as Trait<'a, T, C>>::AssocType;
    const AssocConst: usize = <Base as Trait<'a, T, C>>::AssocConst;
    fn assoc_fn(p: ()) {
        <Base as Trait<'a, T, C>>::assoc_fn(p)
    }
    fn assoc_method(&self, p: ()) {
        // This is the interesting part, everything so far we could just delegate without trouble
        // but here we need to project the field of `self`!
        <Base as Trait<'a, T, C>>::assoc_method(&self.field, p)
    }
}

My question is about the indentation :
Due to this line, there is always two new lines after each element within a block. So I end up with ( don't mind the other mistakes as this is a work in progress :) )

impl<'a, T, const C: usize> Base for S<'a, T, C> {
    type AssocType= <Base as Trait<'a, T, C>>::AssocType;

    const AssocConst: usize = <Base as Trait<'a, T, C>>::AssocConst;

    fn assoc_fn(p: ()) {
    <Base as Trait<'a, T, C>>::assoc_fn(p)
}

    fn assoc_method(&self, p: ()) {
    <Base as Trait<'a, T, C>>::assoc_method(p)
}
}

I can either change the said line to \n, which I believe is not a good idea!
Or I can remove a new line every time a new item has been added.
I would also be very happy if you could tell me why there is an indentation error with R_CURLYs of functions within impl blocks.

@Veykril
Copy link
Member Author

Veykril commented Apr 24, 2023

the empty space bewteen assoc items is essential (my example was just slimmed down), note that formatting of produces nodes is always a bit off. We are missing the infrastructure for formatting these currently. regarding the R_CURLYs you'll need to adjust their indentation manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-assists C-feature Category: feature request E-unknown It's unclear if the issue is E-hard or E-easy without digging in
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants