Songling Lau
Songling Lau

Reputation: 11

Cannot infer an appropriate lifetime for autoref due to conflicting requirements when tried to set a return value with lifetime to a struct


pub struct SumAggregator<'ctx> {
    input: i32,
    state: Cell<Option<IntValue<'ctx>>>,
}

impl<'ctx> SumAggregator<'ctx> {
    pub fn new() -> SumAggregator<'ctx> {
        SumAggregator {
            input: 0,
            state: Cell::new(None),
        }
    }
}

impl<'ctx> Aggregator for SumAggregator<'ctx> {
    fn init(&self, generator: &Generator, layout: &mut Layout, idx: i32) {
        let col_type = generator.context.i32_type();
        self.state.set(Some(col_type.const_int(0, true)));
        generator.build_debug("initialized state value:", self.state.get().unwrap().as_basic_value_enum());
    }

    fn process(&self, val: IntValue) {
        unimplemented!()
    }
}

Above is the core code which throws this error. col_type.const_int(0, true) can return a IntValue with a 'ctx lifetime. When I tried to set this value to my struct, this error occured. I am new to Rust. As far as I know, only references could cause lifetime problem. However, in my use case, I just want to put a value not a reference to a struct(even though this value has a lifetime).

Here is the error stack:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/operator/groupby/mod.rs:40:42
   |
40 |         let col_type = generator.context.i32_type();
   |                                          ^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the method body at 37:5...
  --> src/operator/groupby/mod.rs:37:5
   |
37 |     fn init(&self, generator: &Generator, layout: &mut Layout, idx: i32) {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/operator/groupby/mod.rs:40:24
   |
40 |         let col_type = generator.context.i32_type();
   |                        ^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'ctx` as defined on the impl at 36:6...
  --> src/operator/groupby/mod.rs:36:6
   |
36 | impl<'ctx> Aggregator for SumAggregator<'ctx> {
   |      ^^^^
note: ...so that the expression is assignable
  --> src/operator/groupby/mod.rs:41:24
   |
41 |         self.state.set(Some(col_type.const_int(0, true)));
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `Option<inkwell::values::IntValue<'ctx>>`
              found `Option<inkwell::values::IntValue<'_>>`

Upvotes: 1

Views: 107

Answers (2)

Arman Riazi
Arman Riazi

Reputation: 53

You need to specific all of lets for example:

let int_value:IntValue<'ctx> = col_type.const_int(0, true)

And repeat it for Option and cell left-s.

Consider to a,b,ctx they need more management and if it is possible try it once:

impl<'a,'b,'ctx>

Upvotes: 0

Hadus
Hadus

Reputation: 1664

The problem is that SumAggregator wants to have an IntValue that lives at least as long as itself. But in the init function you are trying to give it an IntValue that lives only until the end of the init function.

You can make sure that the IntValue lives long enough by specifying the Generator's reference's lifetime:

impl<'ctx> Aggregator for SumAggregator<'ctx> {
    fn init(&self, generator: &'ctx Generator, layout: &mut Layout, idx: i32) {
        // col_type is &'ctx IntType
        let col_type = generator.context.i32_type();

        // int_value is &'ctx IntValue
        let int_value = col_type.const_int(0, true)

        // putting &'ctx IntValue into &'ctx IntValue
        self.state.set(Some(int_value));

        generator.build_debug("initialized state value:", self.state.get().unwrap().as_basic_value_enum());
    }

    ...
}

Without doing that it is the same as:

impl<'ctx> Aggregator for SumAggregator<'ctx> {
    fn init<'a, 'b>(&self, generator: &'a Generator, layout: &'b mut Layout, idx: i32) {
        // col_type is &'a IntType
        let col_type = generator.context.i32_type();

        // int_value is &'a IntValue
        let int_value = col_type.const_int(0, true)

        // trying to put &'a IntValue into &'ctx IntValue
        self.state.set(Some(int_value));

        generator.build_debug("initialized state value:", self.state.get().unwrap().as_basic_value_enum());
    }

    ...
}

Upvotes: 0

Related Questions