满足函数参数的生存期

时间:2019-06-18 16:48:34

标签: rust

此代码吸收了replace_with的一些思想并将其扩展到结构,从而允许将函数应用到容器中,从而在出现紧急情况时对其进行清理。与在所有元素上运行replace_with不同,不需要元素类型的默认值,只需容器类型。

我一辈子都做不好。如果我将TStruct替换为Vec<T>,并且在没有生命周期注释的情况下一切正常,那么只有当我尝试概括该函数时,我才会遇到生命周期问题。我需要在这里使用什么寿命才能满足借阅检查员的要求?

fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
    f: impl Fn(T) -> T,
    mut x: TStruct,
) -> TStruct
where
    &mut TStruct: IntoIterator<Item = &mut T>,
    &TStruct: IntoIterator<Item = &T>,
{
    let x_ptr: *mut TStruct = &mut x;
    for item_ref in &mut x {
        let ptr: *mut T = item_ref;
        unsafe {
            let y1: T = std::ptr::read(ptr);
            let fix_missing_elem = RunOnDrop {
                f: || {
                    let y: TStruct = std::ptr::read(x_ptr);
                    let mut i = 0;
                    for item_ref in &y {
                        let current_item_ptr: *const T = item_ref;
                        if current_item_ptr == ptr {
                            break;
                        }
                        i += 1;
                    }

                    let mut j = 0;
                    for elem_ref in y {
                        if j == i {
                            std::mem::forget(elem_ref);
                        }
                        j += 1;
                    }
                    std::ptr::write(x_ptr, <TStruct as Default>::default());
                },
            };
            let result = f(y1);
            std::mem::forget(fix_missing_elem);
            std::ptr::write(ptr, result);
        }
    }
    x
}

struct RunOnDrop<F: FnMut()> {
    f: F,
}

impl<'a, F: FnMut()> Drop for RunOnDrop<F> {
    fn drop(&mut self) {
        (self.f)()
    }
}
error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> src/lib.rs:6:5
  |
6 |     &mut TStruct: IntoIterator<Item = &mut T>,
  |     ^ explicit lifetime name needed here

error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> src/lib.rs:6:39
  |
6 |     &mut TStruct: IntoIterator<Item = &mut T>,
  |                                       ^ explicit lifetime name needed here

error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> src/lib.rs:7:5
  |
7 |     &TStruct: IntoIterator<Item = &T>,
  |     ^ explicit lifetime name needed here

error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> src/lib.rs:7:35
  |
7 |     &TStruct: IntoIterator<Item = &T>,
  |                                   ^ explicit lifetime name needed here

error[E0310]: the parameter type `T` may not live long enough
  --> src/lib.rs:1:1
   |
1  |   fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
   |   ^              - help: consider adding an explicit lifetime bound `T: 'static`...
   |  _|
   | |
2  | |     f: impl Fn(T) -> T,
3  | |     mut x: TStruct,
4  | | ) -> TStruct
...  |
41 | |     x
42 | | }
   | |_^
   |
note: ...so that the reference type `&'static mut T` does not outlive the data it points at
  --> src/lib.rs:1:1
   |
1  | / fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
2  | |     f: impl Fn(T) -> T,
3  | |     mut x: TStruct,
4  | | ) -> TStruct
...  |
41 | |     x
42 | | }
   | |_^

error[E0310]: the parameter type `TStruct` may not live long enough
  --> src/lib.rs:1:1
   |
1  |   fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
   |   ^                 -------- help: consider adding an explicit lifetime bound `TStruct: 'static`...
   |  _|
   | |
2  | |     f: impl Fn(T) -> T,
3  | |     mut x: TStruct,
4  | | ) -> TStruct
...  |
41 | |     x
42 | | }
   | |_^
   |
note: ...so that the reference type `&'static mut TStruct` does not outlive the data it points at
  --> src/lib.rs:1:1
   |
1  | / fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
2  | |     f: impl Fn(T) -> T,
3  | |     mut x: TStruct,
4  | | ) -> TStruct
...  |
41 | |     x
42 | | }
   | |_^

0 个答案:

没有答案