rust-embedded / rust-embedded/heapless

Mutual referencing and self-referencing structures not possible with Vec, FnvIndexMap, SortedLinkedList but with std variants

Open
#296 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug status: blocked
Dominant language
Rust
Stars
2k
Forks
253
Avg merge
1d 2h
Merged PRs (30d)
1

Description

Good day, sorry I don't really know how to name the problem, so here is a "minimal" example.

The following code will lead me into this error:

error[E0597]: `holder.b` does not live long enough
  --> src/main.rs:39:39
   |
39 |     holder.c.lookup.borrow_mut().push(&holder.b);
   |                                       ^^^^^^^^^ borrowed value does not live long enough
40 | }
   | -
   | |
   | `holder.b` dropped here while still borrowed
   | borrow might be used here, when `holder` is dropped and runs the destructor for type `Holder<'_>`
use core::cell::RefCell;

use heapless::{FnvIndexMap, Vec};

struct A {}

struct B<'a> {
    ref_a: RefCell<Option<&'a A>>,
}

struct C<'a> {
    lookup: RefCell<Vec<&'a B<'a>, 4>>,
}

struct Holder<'a> {
    c: C<'a>,
    b: B<'a>,
}

fn main() {
    let c = C {
        lookup: RefCell::new(Vec::new()),
    };

    let b = B {
        ref_a: RefCell::new(None),
    };

    let holder = Holder { c, b };

    holder.c.lookup.borrow_mut().push(&holder.b);
}

But with std::vec::Vec it is fine: lookup: RefCell<Vec<&'a B<'a>>>,
And also with a simple array.

use core::cell::RefCell;

use heapless::{FnvIndexMap, Vec};

struct A {}

struct B<'a> {
    ref_a: RefCell<Option<&'a A>>,
}

struct C<'a> {
    lookup: RefCell<[Option<&'a B<'a>>; 4]>,
}

struct Holder<'a> {
    c: C<'a>,
    b: B<'a>,
}

fn main() {
    let c = C {
        lookup: RefCell::new([None;4]),
    };

    let b = B {
        ref_a: RefCell::new(None),
    };

    let holder = Holder { c, b };

    holder.c.lookup.borrow_mut()[0] = Some(&holder.b);
}

I would expect this to be fine with heapless::Vec as well. The same problem exists with the heapless::FnvIndexMap which uses heapless::Vec internally.
Can this have something to do with the const initialization here ?
So my question is this intentional/ a trade-off that was deliberately chosen?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the minimal Rust example in the issue and compare heapless::Vec with std::vec::Vec and the array variant. Then inspect src/vec.rs around the cited const initialization and trace how FnvIndexMap uses heapless::Vec. Done means establishing whether the lifetime behavior is intentional and documenting the conclusion or adding focused regression coverage if the project supports a fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
data
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.