How to specify lifetime bounds for nested generic associated types

⚓ Rust    📅 2026-02-20    👤 surdeus    👁️ 7      

surdeus

Hi,

I have these traits that describe a multi-level tree, Trunk -> Branch -> Leaf. When you fetch a sub-level it is bound to the lifetime of the level above it.

/// Trunks contain branches
pub trait Trunk {
    /// The Branch type for this trunk.
    ///
    /// Branches can contain a reference back to the trunk.
    type Branch<'t>: Branch where Self: 't;

    /// Fetch a branch
    fn branch(&self) -> Self::Branch<'_>;
}

/// Branches contain leaves
pub trait Branch {
    /// The Leaf type for this branch.
    ///
    /// Leaves can contain a reference back to the branch.
    type Leaf<'b>: where Self: 'b;

    /// Fetch a leaf, converting it to the specified type `T`.
    ///
    /// `T` must implement From<Self::Leaf>
    fn leaf_as<'b, T>(&'b self) -> T
    where
        T: From<Self::Leaf<'b>>;
}

I then want to be able to act on these trees in a general sense:

pub fn use_generic_trunk<T>(trunk: T) -> String
where
    T: Trunk,
    // XXX: What lifetimes can I put here?
    for<'t, 'b> String: From<<T::Branch<'t> as Branch>::Leaf<'b>>,
{
    trunk.branch().leaf_as()
}

But I can't find a way to make the compiler happy with the String: From<...> bound.

For instance, given this specific implementation of the traits:

mod specific_impl {
    pub struct Trunk {
        pub text: String,
    }

    impl super::Trunk for Trunk {
        type Branch<'t> = Branch<'t>;

        fn branch(&self) -> Self::Branch<'_> {
            Branch {
                trunk: self,
            }
        }
    }

    pub struct Branch<'t> {
        trunk: &'t Trunk,
    }

    impl<'t> super::Branch for Branch<'t> {
        type Leaf<'b> = Leaf<'t, 'b> where Self: 'b;

        fn leaf_as<'b, T>(&'b self) -> T
        where
            T: From<Self::Leaf<'b>>,
        {
            T::from(Leaf { branch: self })
        }
    }

    pub struct Leaf<'t, 'b> {
        branch: &'b Branch<'t>,
    }

    impl<'t, 'b> From<Leaf<'t, 'b>> for String {
        fn from(leaf: Leaf<'t, 'b>) -> Self {
            leaf.branch.trunk.text.clone()
        }
    }

    pub fn use_specific_trunk(trunk: Trunk) -> String {
        super::use_generic_trunk::<Trunk>(trunk)
    }
}

The super::use_generic_trunk::<Trunk>(trunk) line produces this compiler error:

error: implementation of `Branch` is not general enough
  --> crate/src/lib.rs:77:9
   |
77 |         super::use_generic_trunk::<Trunk>(trunk)
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Branch` is not general enough
   |
   = note: `Branch` would have to be implemented for the type `specific_impl::Branch<'0>`, for any lifetime `'0`...
   = note: ...but `Branch` is actually implemented for the type `specific_impl::Branch<'1>`, for some specific lifetime `'1`

This approach works with only one level of nesting, I.E. if I was trying to write use_generic_branch rather than use_generic_trunk, but doesn't work with more than one level of nesting.

Is what I'm trying to do possible? Thanks in advance for any help!

1 post - 1 participant

Read full topic

🏷️ Rust_feed