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

GSoC'25: Tool for Automated generic/bounds simplification #2868

Open
addisoncrump opened this issue Jan 20, 2025 · 6 comments
Open

GSoC'25: Tool for Automated generic/bounds simplification #2868

addisoncrump opened this issue Jan 20, 2025 · 6 comments
Assignees
Labels
help wanted Extra attention is needed rfc Request for comment -- your input is desired!

Comments

@addisoncrump
Copy link
Collaborator

addisoncrump commented Jan 20, 2025

As commented by many users and maintainers of LibAFL, our codebase is absolutely full of complicated generics. We use these to allow for structured and statically-checked compatibility between various components provided in our codebase, and is a critical part of how LibAFL is structured.

Unfortunately, these can be very difficult to maintain. Our goal is to develop a tool capable of assisting developers in this maintenance process.


Consider a code sequence like the following:

trait Trait1 {}
trait Trait2<A>
where
  A: Trait1
{}

struct Thing1;
struct Thing2<I>(I);

impl<A> Trait2<A> for Thing1
where
  A: Trait1
{}

impl<A> Trait2<A> for Thing2<Thing1>
where
  A: Trait1,
{
  // implement using Thing1's implementation
}

Suppose we change Trait2 now to not include the bound A: Trait1:

2,5c2
< trait Trait2<A>
< where
<     A: Trait1
< {}
---
> trait Trait2<A> {}

Maybe Thing1's implementation of Trait2 doesn't internally depend on A: Trait1; then neither does Thing2's! So, our actual diff should be:

2,5c2
< trait Trait2<A>
< where
<     A: Trait1
< {}
---
> trait Trait2<A> {}
10,13c7
< impl<A> Trait2<A> for Thing1
< where
<     A: Trait1
< {}
---
> impl<A> Trait2<A> for Thing1 {}
15,18c9
< impl<A> Trait2<A> for Thing2<Thing1>
< where
<     A: Trait1,
< {
---
> impl<A> Trait2<A> for Thing2<Thing1> {

Consider another case, shown below, where we have a mutually recursive pair of functions:

trait Trait {}

fn first<A>(should: bool)
where
    A: Trait,
{
    if should {
        second::<A>(!should)
    }
}

fn second<A>(should: bool)
where
    A: Trait,
{
    if should {
        first::<A>(!should)
    }
}

If neither of the functions actually use the bound, then it should be dropped. But this requires the knowledge that they can both be simultaneously dropped:

3,6c3
< fn first<A>(should: bool)
< where
<     A: Trait,
< {
---
> fn first<A>(should: bool) {
12,15c9
< fn second<A>(should: bool)
< where
<     A: Trait,
< {
---
> fn second<A>(should: bool) {

Furthermore, neither function even uses the generic argument! So this could itself be rewritten:

3,6c3
< fn first<A>(should: bool)
< where
<     A: Trait,
< {
---
> fn first(should: bool) {
8c5
<         second::<A>(!should)
---
>         second(!should)
12,15c9
< fn second<A>(should: bool)
< where
<     A: Trait,
< {
---
> fn second(should: bool) {
17c11
<         first::<A>(!should)
---
>         first(!should)

In short, these issues cause numerous maintenance issues, several of which are outlined in CONTRIBUTING.md, but are in reality very hard to enforce. For this reason, we are opening a GSOC project, which we would like to supervise into potentially a bachelor's/master's thesis or workshop paper, in which we will implement a tool to perform "generic shaking". This entails:

  1. Removes overspecified generic bounds.
  2. Removes overspecified associated types (e.g., instead of <A, B<Thing=A>>, just <B>).
  3. Removes overspecified generics, including in PhantomData declarations.
  4. Removes overspecified lifetimes.
  5. Successfully is able to do both of the above in the presence of dependency cycles (see example 2).

This is a project that likely requires some background in Rust compiler infrastructure and type theory in general. For this reason, we are opening this up specifically to candidates who already have some experience in one or preferably both. If a suitable candidate is not identified for GSoC, we will postpone the project; the current maintainers do not currently have the time to execute this project ourselves.

To ensure that the project is well-considered before beginning, I have marked this issue with "rfc"; community input, especially from Rust maintainers who have previously interacted with our code, will considerably support any candidate picking this up will be suitably prepared for potential problems along the way. We believe that, written well, such a tool would be useful for many organisations using component-based Rust codebases.

To contact us, please send an email to [email protected]

@addisoncrump addisoncrump added help wanted Extra attention is needed rfc Request for comment -- your input is desired! labels Jan 20, 2025
@addisoncrump addisoncrump self-assigned this Jan 20, 2025
@addisoncrump
Copy link
Collaborator Author

Historically, we had considered doing this incrementally -- by progressively deleting bounds and attempting recompilation in a very-low optimisation mode -- but mutual recursion (or, really, dependency cycles in general) makes this potentially ineffective in some cases. As a "first effort", this probably would be worth trying.

There is another case we would like to solve as well, e.g.:

trait Trait1 {}
trait Trait2 {}

trait Trait3: Trait1 + Trait2 {}

fn thing<A: Trait3>() {...}

If the bound A: Trait3 is not necessary, but Trait2 is, then we would want to replace the trait with its constituent requirements, then continue. But this makes the process once again rather complicated...

@addisoncrump addisoncrump changed the title GSoC'25: Generic/Bounds simplification GSoC'25: Automated generic/bounds simplification Jan 20, 2025
@tokatoka tokatoka pinned this issue Jan 20, 2025
@tokatoka tokatoka changed the title GSoC'25: Automated generic/bounds simplification GSoC'25: Tool for Automated generic/bounds simplification Jan 20, 2025
@Gulshan1-3
Copy link

I am interested in solving this problem ,I have mailed you about my progress.Can you check it and guide me further

@addisoncrump
Copy link
Collaborator Author

Hey @Gulshan1-3, thanks for letting us know. We aren't currently asking for work to be completed on this, and anything completed in advance will not be considered for the application process as a matter of fairness.

While extracting the traits and lifetime data (like your examples in the email you sent show) will be necessary, this is one of potentially many steps necessary to accomplish this. Again, out of fairness, we will not be supervising any progress before the application and acceptance process is complete.

@Gulshan1-3
Copy link

Can I work on it on my own though as you wont be able to help I am thinking of figuring out things on my own n proceed further, thanks for replying

@addisoncrump
Copy link
Collaborator Author

Of course. We will likely host conversations here about our preferred design, which may diverge from yours quite a bit by the time the application process completes.

@Gulshan1-3
Copy link

Thanks for the help, have a great day!! @addisoncrump

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed rfc Request for comment -- your input is desired!
Projects
None yet
Development

No branches or pull requests

2 participants