title: Rust lifetimes, data flows into other references
body: <p>I wrote the following code that filters a stream of data which worked fine until I changed from parsing simple numbers to also have types that are bound to lifetimes like <code>&amp;str</code> and <code>&amp;[u8]</code>.</p>
  
  <pre class="lang-rust prettyprint-override"><code>use wirefilter::{ExecutionContext, Filter, Scheme};
  
  lazy_static::lazy_static! {
      static ref SCHEME: Scheme = Scheme! {
          port: Int,
          name: Bytes,
      };
  }
  
  #[derive(Debug)]
  struct MyStruct {
      port: i32,
      name: String,
  }
  
  impl MyStruct {
      fn scheme() -&gt; &amp;'static Scheme {
          &amp;SCHEME
      }
  
      fn filter_matches&lt;'s&gt;(&amp;self, filter: &amp;Filter&lt;'s&gt;) -&gt; bool {
          let mut ctx = ExecutionContext::new(Self::scheme());
          ctx.set_field_value("port", self.port).unwrap();
          ctx.set_field_value("name", self.name.as_str()).unwrap();
  
          filter.execute(&amp;ctx).unwrap()
      }
  }
  
  fn main() -&gt; Result&lt;(), failure::Error&gt; {
      let data = expensive_data_iterator();
      let scheme = MyStruct::scheme();
      let filter = scheme
          .parse("port in {2 5} &amp;&amp; name matches \"http.*\"")?
          .compile();
  
      for my_struct in data
          .filter(|my_struct| my_struct.filter_matches(&amp;filter))
          .take(2)
      {
          println!("{:?}", my_struct);
      }
  
      Ok(())
  }
  
  fn expensive_data_iterator() -&gt; impl Iterator&lt;Item = MyStruct&gt; {
      (0..).map(|port| MyStruct {
          port,
          name: format!("http {}", port % 2),
      })
  }
  
  </code></pre>
  
  <p>If I try to compile it the compiler will fail with this:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0623]: lifetime mismatch
    --&gt; src/main.rs:26:16
     |
  21 |     fn filter_matches&lt;'s&gt;(&amp;self, filter: &amp;Filter&lt;'s&gt;) -&gt; bool {
     |                           -----           ----------
     |                           |
     |                           these two types are declared with different lifetimes...
  ...
  26 |         filter.execute(&amp;ctx).unwrap()
     |                ^^^^^^^ ...but data from `self` flows into `filter` here
  
  error: aborting due to previous error
  
  error: Could not compile `wirefilter_playground`.
  
  To learn more, run the command again with --verbose.
  
  Process finished with exit code 101
  </code></pre>
  
  <p>my first thought was that self and filter should have the same lifetime in <code>fn filter_matches&lt;'s&gt;(&amp;self, filter: &amp;Filter&lt;'s&gt;) -&gt; bool</code> but if I change the signature to <code>fn filter_matches&lt;'s&gt;(&amp;'s self, filter: &amp;Filter&lt;'s&gt;) -&gt; bool</code> I will start getting this error:</p>
  
  <pre class="lang-none prettyprint-override"><code>error: borrowed data cannot be stored outside of its closure
    --&gt; src/main.rs:38:29
     |
  33 |     let filter = scheme
     |         ------ ...so that variable is valid at time of its declaration
  ...
  38 |         .filter(|my_struct| my_struct.filter_matches(&amp;filter))
     |                 ----------- ^^^^^^^^^ -------------- cannot infer an appropriate lifetime...
     |                 |           |
     |                 |           cannot be stored outside of its closure
     |                 borrowed data cannot outlive this closure
  
  error: aborting due to previous error
  
  error: Could not compile `wirefilter_playground`.
  
  To learn more, run the command again with --verbose.
  
  Process finished with exit code 101
  
  </code></pre>
  
  <p>I am failing to understand the reason, <code>Filter&lt;'s&gt;</code> is bound to <code>SCHEME</code> which is lazily generated and is bound to <code>'static</code> which makes sense not allowing filter.execute to take reference to <code>&amp;self.name.as_str()</code> because it would be outlived but, isn't <code>filter.execute(&amp;ctx)</code> which the signature is <code>pub fn execute(&amp;self, ctx: &amp;ExecutionContext&lt;'s&gt;) -&gt; Result&lt;bool, SchemeMismatchError&gt;</code> supposed to drop the references as soon as it finishes as the result of it has not other lifetimes?</p>
  
  <p>In order to try and compile the code above, you can use this <code>Cargo.toml</code>:</p>
  
  <pre><code>[package]
  name = "wirefilter_playground"
  version = "0.1.0"
  edition = "2018"
  
  [dependencies]
  wirefilter-engine = "0.6.1"
  failure = "0.1.5"
  lazy_static = "1.3.0"
  
  </code></pre>
  
  <p>PS: That could be solved by compiling the as inside <code>filter_matches</code> method but that would be sort of bad because the user would only get the parse error when trying to filter and it could potentially be slower.</p>