someguynamedjosh / ouroboros

Easy self-referential struct generation for Rust.
Apache License 2.0
535 stars 34 forks source link

Self-referencing hierarchy (need help) #94

Closed muja closed 1 year ago

muja commented 1 year ago

Hi, I have the following solution for a use case: write a container that represents an MS Word (docx) file. A docx file is just a zip archive with a dozen XML files. I've tried a lot of different solutions and this is where I've landed, but it won't compile: owned file with a zip Archive struct struct borrowing the file, a ZipReader borrowing the Archive and a XMLReader borrowing the ZipReader

#[self_referencing]
pub struct DocxProcessor {
    file: std::fs::File,
    #[borrows(file)]
    #[covariant]
    arc: rc_zip::reader::sync::SyncArchive<'this, File>,
    #[borrows(arc)]
    #[covariant]
    entry_reader: rc_zip::reader::sync::EntryReader<<File as HasCursor>::Cursor<'this>>,
    #[borrows(entry_reader)]
    #[covariant]
    reader: xml::EventReader<rc_zip::reader::sync::EntryReader<<File as HasCursor>::Cursor<'this>>>,
}

The error I'm getting:

image

Notes: I'm using xml-rs crate for XML reading and for ZIP I'm using rc_zip crate from my main branch: https://github.com/muja/rc-zip

Any idea what I'm doing wrong?

kpreid commented 1 year ago

I don't know if this is the actual problem, but it doesn't look like #[borrows(entry_reader)] is correct for reader; the EventReader type owns the parameter, and doesn't borrow it, so it must be borrowing from elsewhere than the entry_reader field (presumably file).

someguynamedjosh commented 1 year ago

Looks like this is a problem with the internal generation of the BorrowedFields struct, it should contain a bound that 'this outlives 'outer_borrow, but it was missing. This is now fixed in 0.17.2

muja commented 1 year ago

I don't know if this is the actual problem, but it doesn't look like #[borrows(entry_reader)] is correct for reader; the EventReader type owns the parameter, and doesn't borrow it, so it must be borrowing from elsewhere than the entry_reader field (presumably file).

Yes that's a valid concern but in this stage the compiler doesn't know from the struct signature that there is no practicable to obtain an owned EntryReader from a borrowed one. So that couldn't be it. And, I actually tried multiple different variants, just ended up with this otherwise-faulty one :)

@joshua-maros thank you so much, it works now. I tried all weekend to get this to work and was really desparate!