代码之家  ›  专栏  ›  技术社区  ›  dspyz

使用幻象作用域绕过边界检查

  •  0
  • dspyz  · 技术社区  · 5 年前

    我想构造一个与值关联的索引类型,该值是一个 usize 这样,从该值创建的任何向量,我都不需要检查索引。似乎幻影的生命周期可以用来做一些少量的依赖类型的编程,就像这样。这能行吗?还是有什么我没有考虑的?

    换句话说,使用下面的模块是否不可能编写出内存不足的“安全”代码?

    还有,有没有办法在没有单元参考的情况下做到这一点?

    pub mod things {
        use std::iter;
    
        #[derive(Clone, Copy)]
        pub struct ThingIndex<'scope>(usize, &'scope ());
        pub struct Things {
            nthings: usize,
        }
        pub struct ThingMapping<'scope, V>(Vec<V>, &'scope ());
    
        impl Things {
            pub fn in_context<F: FnOnce(&Things) -> V, V>(nthings: usize, continuation: F) -> V {
                continuation(&Things { nthings })
            }
            pub fn make_index<'scope>(&'scope self, i: usize) -> ThingIndex<'scope> {
                if i >= self.nthings {
                    panic!("Out-of-bounds index!")
                }
                ThingIndex(i, &())
            }
            pub fn make_mapping<'scope, V: Clone>(&'scope self, def: V) -> ThingMapping<'scope, V> {
                ThingMapping(iter::repeat(def).take(self.nthings).collect(), &())
            }
        }
    
        impl<'scope, V> ThingMapping<'scope, V> {
            pub fn get<'a>(&'a self, ind: ThingIndex<'scope>) -> &'a V {
                unsafe { &self.0.get_unchecked(ind.0) }
            }
            // ...
        }
    }
    

    更新:

    这似乎不起作用。我添加了一个我预计无法编译的测试,它编译时没有抱怨。有没有办法修复它并使其正常工作?如果我写一个宏呢?

    #[cfg(test)]
    mod tests {
        use crate::things::*;
    
        #[test]
        fn it_fails() {
            Things::in_context(1, |r1| {
                Things::in_context(5, |r2| {
                    let m1 = r1.make_mapping(());
                    let i2 = r2.make_index(3);
                    assert_eq!(*m1.get(i2), ());
                });
            })
        }
    }
    

    注: in_context 大致基于Haskell的 runST 作用Haskell中的类型签名 朗斯特 要求 RankNTypes .我想知道这是否是不可能的,因为Rust编译器不会与 兰开佩斯 .

    0 回复  |  直到 5 年前