You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Wasm场景下如何声明元素生命周期与迭代器一致的Rust迭代器?

问题:实现元素生命周期与迭代器绑定的迭代器

最终目标是将Vec<v128>当作Vec<i16>来迭代,遍历v128中打包的i16元素。

初始编译错误

[INFO]: Checking for the Wasm target...
[INFO]: Compiling to Wasm...
   Compiling snakelib v0.1.0 (/home/jeff/gitrepos/code/code/pdfsnake/firebase/webapp/wasm)
error: lifetime may not live long enough
   --> pdfsnake/firebase/webapp/wasm/src/i16word_wasm.rs:214:13
    |
207 | impl<'a> Iterator for I16WordIterMut<'a> {
    |      -- lifetime `'a` defined here
...
210 |     fn next(&mut self) -> Option<Self::Item> {
    |             - let's call the lifetime of this reference `'1`
...
214 |             Some(n)
    |             ^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

error: could not compile `snakelib` (lib) due to previous error
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit status: 101
  full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"

相关代码

use core::arch::wasm32;

const I16_COUNT: usize = 8;

#[derive(Debug, Clone, Copy)]
pub struct I16Word {
    pub w: wasm32::v128
}


impl From<&mut I16Word> for [i16; I16_COUNT] {
    fn from(w: &mut I16Word) -> [i16; I16_COUNT] {
        [
            wasm32::i16x8_extract_lane::<0>(w.w),
            wasm32::i16x8_extract_lane::<1>(w.w),
            wasm32::i16x8_extract_lane::<2>(w.w),
            wasm32::i16x8_extract_lane::<3>(w.w),
            wasm32::i16x8_extract_lane::<4>(w.w),
            wasm32::i16x8_extract_lane::<5>(w.w),
            wasm32::i16x8_extract_lane::<6>(w.w),
            wasm32::i16x8_extract_lane::<7>(w.w)
        ]
    }
}

impl I16Word {
    pub fn iter_mut(&mut self) -> I16WordIterMut {
        let slice: [i16; I16_COUNT] = self.into();
        I16WordIterMut { word: slice, i16word: self, index: 0 }
    }

}

pub struct I16WordIterMut<'a> {
    word: [i16; I16_COUNT],
    i16word: &'a mut I16Word,
    index: usize
}

impl<'a> Iterator for I16WordIterMut<'a> {
    type Item = &'a mut i16;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index < I16_COUNT {
            let n = &mut self.word[self.index];
            self.index += 1;
            Some(n)
        } else {
            None
        }
    }
}

impl<'a> Drop for I16WordIterMut<'a> {
    fn drop(&mut self) {
        *self.i16word = (&self.word).into();
    }
}

由于底层wasm32::v128无法直接获取&mut i16,所以在迭代器中保留了一份副本。因为迭代器持有容器的可变引用,其他对象无法读写该容器,因此在迭代器销毁时将内容复制回容器应该是安全的。理解错误信息的含义,但找不到修复方法或替代方案。

更新:采用解决方案后的新错误

采用Chayim的解决方案后,原代码编译通过,但调用代码出现类型不匹配错误:

[INFO]: Checking for the Wasm target...
[INFO]: Compiling to Wasm...
   Compiling snakelib v0.1.0 (/home/jeff/gitrepos/code/code/pdfsnake/firebase/webapp/wasm)
error[E0308]: mismatched types
   --> pdfsnake/firebase/webapp/wasm/src/i16vec.rs:161:26
    |
161 |                 self.j = self.i.next().map(|w| w.iter_mut());
    |                 ------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<IterMut<'_, i16>>`, found `Option<I16WordIterMut<'_>>`
    |                 |
    |                 expected due to the type of this binding
    |
    = note: expected enum `std::option::Option<std::slice::IterMut<'a, i16>>`
               found enum `std::option::Option<I16WordIterMut<'_>>`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `snakelib` (lib) due to previous error
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit status: 101
  full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"

调用代码

pub struct I16VecIterMut<'a> {
    i: std::slice::IterMut<'a, I16Word>,
    j: Option<std::slice::IterMut<'a, i16>>,
    remaining: usize
}

impl<'a> Iterator for I16VecIterMut<'a> {
    type Item = &'a mut i16;

    fn next(&mut self) -> Option<Self::Item> {
        if self.remaining < 1 {
            return None;
        }
        self.remaining -= 1;
        for _ in 0..2 {
            if self.j.is_none() {
                self.j = self.i.next().map(|w| w.iter_mut());
            }
            match self.j {
                Some(ref mut j) => match j.next() {
                    Some(n) => return Some(n),
                    None => {
                        self.j = None;
                    }   
                },
                None => return None
            }
        }
        panic!("I16VecIterMut::next() loop error")
    }
}

内容的提问来源于stack exchange,提问作者Jeffrey Rennie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 16:30:57