Skip to content

Inflexible function signature for Interner trait #185

@h3har

Description

@h3har

The function signature for Interner::display_merged_solvables is:

fn display_merged_solvables(&self, solvables: &[SolvableId]) -> impl std::fmt::Display + '_

However, the elided lifetimes prevent returning a Display-able struct that borrows from both arguments. This prevents you from writing a display implementation that avoids allocating or cloning unnecessarily, which might look like:

fn display_merged_solvables(&self, solvables: &[SolvableId]) -> impl std::fmt::Display + '_ {
    struct DisplayMergedSolvables<'a, 'b>(&'a ProviderType, &'b [SolvableId]);
    
    impl<'a, 'b> std::fmt::Display for DisplayMergedSolvables<'a, 'b> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            todo!("insert implementation here")
        }
    }

    DisplayMergedSolvables(self, solvables)
}

This is because of how Rust's lifetime elision rules work. In particular, see the following from the Rustnomicon:

Elision rules are as follows:

  • Each elided lifetime in input position becomes a distinct lifetime parameter.
  • ...
  • If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.

In particular, the return value cannot borrow from solvables, since solvables has an independent lifetime of self, and - as per the above rules - the returned lifetime must equal the lifetime of self.

Adding lifetime parameters to the trait would be a breaking change, since they would conflict with the original trait definition. Perhaps if a new major release is added in the future that this problem is avoided with specific lifetime bounds. Otherwise, this is quite a minor issue.

Since the other methods of the Interner trait only borrow from self, this method is the only one that is affected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions