Commit bf871ffd authored by Matt Mastracci's avatar Matt Mastracci Committed by Robert

Remove lifetime specifier on table getter methods (#4949)

With the old-style code, the test fails with a borrow-checker error:

```
  #[inline]
  pub fn name(&'a self) -> &'a str {
    self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(Monster::VT_NAME, None).unwrap()
  }
```

```
error[E0597]: `e` does not live long enough
   --> tests/integration_test.rs:273:57
    |
273 |         let enemy_of_my_enemy = monster.enemy().map(|e| e.name());
    |                                                         ^      - `e` dropped here while still borrowed
    |                                                         |
    |                                                         borrowed value does not live long enough
274 |         assert_eq!(enemy_of_my_enemy, Some("Fred"));
275 |     }
    |     - borrowed value needs to live until here
```
parent a89be873
...@@ -1263,7 +1263,7 @@ class RustGenerator : public BaseGenerator { ...@@ -1263,7 +1263,7 @@ class RustGenerator : public BaseGenerator {
GenComment(field.doc_comment, " "); GenComment(field.doc_comment, " ");
code_ += " #[inline]"; code_ += " #[inline]";
code_ += " pub fn {{FIELD_NAME}}(&'a self) -> {{RETURN_TYPE}} {"; code_ += " pub fn {{FIELD_NAME}}(&self) -> {{RETURN_TYPE}} {";
code_ += " {{FUNC_BODY}}"; code_ += " {{FUNC_BODY}}";
code_ += " }"; code_ += " }";
......
This diff is collapsed.
...@@ -184,7 +184,7 @@ impl<'a> TableInNestedNS<'a> { ...@@ -184,7 +184,7 @@ impl<'a> TableInNestedNS<'a> {
pub const VT_FOO: flatbuffers::VOffsetT = 4; pub const VT_FOO: flatbuffers::VOffsetT = 4;
#[inline] #[inline]
pub fn foo(&'a self) -> i32 { pub fn foo(&self) -> i32 {
self._tab.get::<i32>(TableInNestedNS::VT_FOO, Some(0)).unwrap() self._tab.get::<i32>(TableInNestedNS::VT_FOO, Some(0)).unwrap()
} }
} }
......
...@@ -55,15 +55,15 @@ impl<'a> TableInFirstNS<'a> { ...@@ -55,15 +55,15 @@ impl<'a> TableInFirstNS<'a> {
pub const VT_FOO_STRUCT: flatbuffers::VOffsetT = 8; pub const VT_FOO_STRUCT: flatbuffers::VOffsetT = 8;
#[inline] #[inline]
pub fn foo_table(&'a self) -> Option<namespace_b::TableInNestedNS<'a>> { pub fn foo_table(&self) -> Option<namespace_b::TableInNestedNS<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<namespace_b::TableInNestedNS<'a>>>(TableInFirstNS::VT_FOO_TABLE, None) self._tab.get::<flatbuffers::ForwardsUOffset<namespace_b::TableInNestedNS<'a>>>(TableInFirstNS::VT_FOO_TABLE, None)
} }
#[inline] #[inline]
pub fn foo_enum(&'a self) -> namespace_b::EnumInNestedNS { pub fn foo_enum(&self) -> namespace_b::EnumInNestedNS {
self._tab.get::<namespace_b::EnumInNestedNS>(TableInFirstNS::VT_FOO_ENUM, Some(namespace_b::EnumInNestedNS::A)).unwrap() self._tab.get::<namespace_b::EnumInNestedNS>(TableInFirstNS::VT_FOO_ENUM, Some(namespace_b::EnumInNestedNS::A)).unwrap()
} }
#[inline] #[inline]
pub fn foo_struct(&'a self) -> Option<&'a namespace_b::StructInNestedNS> { pub fn foo_struct(&self) -> Option<&'a namespace_b::StructInNestedNS> {
self._tab.get::<namespace_b::StructInNestedNS>(TableInFirstNS::VT_FOO_STRUCT, None) self._tab.get::<namespace_b::StructInNestedNS>(TableInFirstNS::VT_FOO_STRUCT, None)
} }
} }
...@@ -151,7 +151,7 @@ impl<'a> SecondTableInA<'a> { ...@@ -151,7 +151,7 @@ impl<'a> SecondTableInA<'a> {
pub const VT_REFER_TO_C: flatbuffers::VOffsetT = 4; pub const VT_REFER_TO_C: flatbuffers::VOffsetT = 4;
#[inline] #[inline]
pub fn refer_to_c(&'a self) -> Option<super::namespace_c::TableInC<'a>> { pub fn refer_to_c(&self) -> Option<super::namespace_c::TableInC<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_c::TableInC<'a>>>(SecondTableInA::VT_REFER_TO_C, None) self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_c::TableInC<'a>>>(SecondTableInA::VT_REFER_TO_C, None)
} }
} }
...@@ -241,11 +241,11 @@ impl<'a> TableInC<'a> { ...@@ -241,11 +241,11 @@ impl<'a> TableInC<'a> {
pub const VT_REFER_TO_A2: flatbuffers::VOffsetT = 6; pub const VT_REFER_TO_A2: flatbuffers::VOffsetT = 6;
#[inline] #[inline]
pub fn refer_to_a1(&'a self) -> Option<super::namespace_a::TableInFirstNS<'a>> { pub fn refer_to_a1(&self) -> Option<super::namespace_a::TableInFirstNS<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::TableInFirstNS<'a>>>(TableInC::VT_REFER_TO_A1, None) self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::TableInFirstNS<'a>>>(TableInC::VT_REFER_TO_A1, None)
} }
#[inline] #[inline]
pub fn refer_to_a2(&'a self) -> Option<super::namespace_a::SecondTableInA<'a>> { pub fn refer_to_a2(&self) -> Option<super::namespace_a::SecondTableInA<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::SecondTableInA<'a>>>(TableInC::VT_REFER_TO_A2, None) self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::SecondTableInA<'a>>>(TableInC::VT_REFER_TO_A2, None)
} }
} }
......
...@@ -263,6 +263,23 @@ mod lifetime_correctness { ...@@ -263,6 +263,23 @@ mod lifetime_correctness {
// this line should compile: // this line should compile:
table.get::<&'static str>(0, None); table.get::<&'static str>(0, None);
} }
#[test]
fn table_object_self_lifetime_in_closure() {
// This test is designed to ensure that lifetimes for temporary intermediate tables aren't inflated beyond where the need to be.
let buf = load_file("../monsterdata_test.mon");
let monster = my_game::example::get_root_as_monster(&buf);
let enemy: Option<my_game::example::Monster> = monster.enemy();
// This line won't compile if "self" is required to live for the lifetime of buf above as the borrow disappears at the end of the closure.
let enemy_of_my_enemy = enemy.map(|e| {
// enemy (the Option) is consumed, and the enum's value is taken as a temporary (e) at the start of the closure
let name = e.name();
// ... the temporary dies here, so for this to compile name's lifetime must not be tied to the temporary
name
// If this test fails the error would be "`e` dropped here while still borrowed"
});
assert_eq!(enemy_of_my_enemy, Some("Fred"));
}
} }
#[cfg(test)] #[cfg(test)]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment