Flatbuffers: Rust - cannot infer an appropriate lifetime for autoref due to conflicting requirements

Created on 3 Oct 2018  路  14Comments  路  Source: google/flatbuffers

In my project I'm observing many similar erros like:
Using
cargo 1.28.0
rustc 1.28.0 (9634041f0 2018-07-30)

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  240 |     self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(OutBlock::VT_SERVICE_NAME, None)
    |               ^^^
  note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 239:3...
      |
239 |   pub fn service_name(&self) -> Option<&'a str> {
240 | |     self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(OutBlock::VT_SERVICE_NAME, None)
241 | |   }
    | |___^
note: ...so that reference does not outlive borrowed content
    |
240 |     self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(OutBlock::VT_SERVICE_NAME, None)
    |     ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 218:1...
    |
218 | impl<'a> OutBlock<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...so that the expression is assignable:
            expected std::option::Option<&'a str>
               found std::option::Option<&str>

My schema structure is

namespace arprotocol;

// Image format types
enum Format : ubyte { LAB = 0, RGBX = 1, GRAY = 10 }

table OutImage {
    // Image format code
    fmt: Format;
    width: uint16;
    height: uint16;
    // Content length should be width*height
    content: [ubyte];
}

// Single output block related to particular service in processing chain
table OutBlock {
    service_name: string;
    images: [OutImage];
}

table ServiceResponse {
    // Is response succesfull or not
    success: bool;
    // Should have some info on error
    message: string;
    // Number of media blocks attached
    blocks:[OutBlock];
}

root_type ServiceResponse;
stale

Most helpful comment

It looks like I was using incompatible versions of flatc vs. the flatbuffers crate. Upgrading to the latest flatbuffers fixed my issue. Sorry for the false alarm!

All 14 comments

@rumatoest If you use the latest master version of flatbuffers, does this problem still happen?

Yes it was latest master version

I hit this problem as well. I did not precisely bisect the offending commit, but I suspect #4949 was the cause. I rolled back to the commit before that PR was merged and it solved the issue. In case it's helpful, our schema is public and can be seen here.

@whatisaphone @rumatoest would you please post the code you have written that causes these errors? I ask because debugging lifetimes can be tricky without all the context (because of the constraint-satisfaction methods Rust seems to use to resolve lifetimes).

Most importantly, code samples can help us write regression tests so that this doesn't happen in the future.

I'm getting this error in the latest master version of flatbuffers.
cargo 1.31.0-nightly
rustc 1.31.0-nightly

My schema can be found here.

Example errors are:

E0495

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
   --> data_structures/src/flatbuffers/protocol_generated.rs:206:15
    |
206 |     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Message::VT_COMMAND, None).unwrap()
    |               ^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 205:3...
   --> data_structures/src/flatbuffers/protocol_generated.rs:205:3
    |
205 | /   pub fn command(&self) -> flatbuffers::Table<'a> {
206 | |     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Message::VT_COMMAND, None).unwrap()
207 | |   }
    | |___^
note: ...so that reference does not outlive borrowed content
   --> data_structures/src/flatbuffers/protocol_generated.rs:206:5
    |
206 |     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Message::VT_COMMAND, None).unwrap()
    |     ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 174:6...
   --> data_structures/src/flatbuffers/protocol_generated.rs:174:6
    |
174 | impl<'a> Message<'a> {
    |      ^^
    = note: ...so that the types are compatible:
            expected serializers::flatbuffers::Follow<'_>
               found serializers::flatbuffers::Follow<'_>

E0599

error[E0599]: no method named `map` found for type `serializers::flatbuffers::Table<'_>` in the current scope
   --> data_structures/src/flatbuffers/protocol_generated.rs:212:22
    |
212 |       self.command().map(|u| Version::init_from_table(u))
    |                      ^^^
    |
    = note: the method `map` exists but the following trait bounds were not satisfied:
            `&mut serializers::flatbuffers::Table<'_> : std::iter::Iterator`

error[E0599]: no method named `map` found for type `serializers::flatbuffers::Table<'_>` in the current scope
   --> data_structures/src/flatbuffers/protocol_generated.rs:222:22
    |
222 |       self.command().map(|u| Verack::init_from_table(u))
    |                      ^^^
    |
    = note: the method `map` exists but the following trait bounds were not satisfied:
            `&mut serializers::flatbuffers::Table<'_> : std::iter::Iterator`

@Tommytrg Does this happen on Rust stable? The .map is on an Option -- there is no iterator there -- not sure how that could possibly happen.

@whatisaphone bump

I've avoided E0599, .map error one, removing the required field from our table Message:

union Command (required) { Version, Verack, GetPeers, Peers, Ping, Pong }

table Message {
    magic: uint16;
    command: Command;
}

Then the generated code is:

  #[inline]
  pub fn command(&self) -> Option<flatbuffers::Table<'a>> {
    self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Message::VT_COMMAND, None)
  }

Instead, when I compile table Message with required field:

union Command (required) { Version, Verack, GetPeers, Peers, Ping, Pong }

table Message {
    magic: uint16;
    command: Command (required);
}

I get the code that produces mentioned E0599 error:

  #[inline]
  pub fn command(&self) -> flatbuffers::Table<'a> {
    self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Table<'a>>>(Message::VT_COMMAND, None).unwrap()
  }

Could be a problem with required union fields? We want to use required modifiers as it is needed to specify our protocol.
By the other hand, I still get the E0495 which this issue is about.

1) @Tommytrg @whatisaphone Could you please post all the code that causes E0495? I need this to include your schema, the generated flatbuffers code, _and_ the code that calls the generated code.

2) @Tommytrg Thanks for digging into the required issue about unions! I think I understand the problem: the typed union accessors assume that the underlying data is wrapped in an Option. I can open a PR to fix it--but would you like to try? I'd appreciate the help! The change would be to skip the .map if the field is required: you would make the change in the Rust code generator.

I'll put together some repro steps this weekend.

It looks like I was using incompatible versions of flatc vs. the flatbuffers crate. Upgrading to the latest flatbuffers fixed my issue. Sorry for the false alarm!

@Tommytrg bump!

Upgrading to latest flatbuffers crate fixed E0495. By the other hand, I'm still getting E0599. I've opened #5056 to track this issue and I've made a PR to solve it.

This issue has been automatically marked as stale because it has not had activity for 6 months. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NN--- picture NN---  路  6Comments

Dmitry-N-Medvedev picture Dmitry-N-Medvedev  路  9Comments

cberner picture cberner  路  3Comments

lixin-wei picture lixin-wei  路  7Comments

eduardosm picture eduardosm  路  3Comments