标签: borrowing

为什么通过原始指针修改可变引用的值不违反Rust的别名规则?

我没有锈的别名规则特别深刻的理解(从我听说他们没有扎实的定义),但我无法理解是什么使这个代码示例std::slice文档还好.我在这里重复一遍:

let x = &mut [1, 2, 4];
let x_ptr = x.as_mut_ptr();

unsafe {
    for i in 0..x.len() {
        *x_ptr.offset(i as isize) += 2;
    }
}
assert_eq!(x, &[3, 4, 6]);
Run Code Online (Sandbox Code Playgroud)

我在这里看到的问题是x,作为&mut参考,可以假设编译器是唯一的.xget 的内容经过修改x_ptr,然后通过回读x,我认为没有理由为什么编译器不能假设x没有被修改,因为它从未通过唯一的现有&mut引用进行修改.

那么,我在这里错过了什么?

  • 编译器是否需要假设*mut T可能是别名&mut T,即使通常允许它假设&mut T 永远不会别名别名&mut T

  • unsafe块是否充当某种别名障碍,编译器假定其中的代码可能已修改了范围内的任何内容?

  • 此代码示例是否已损坏?

如果有某种稳定的规则使这个例子没问题,究竟是什么呢?它的范围是多少?我应该担心多少假设破坏unsafeRust代码中的随机事物?

pointers unsafe rust borrowing

8
推荐指数
1
解决办法
274
查看次数

使用相关类型的特征与生命周期参数的生命周期错误

由于使用了相关类型,我在Rust 1.14中遇到了一生的错误,由以下两个类似的程序演示,第一个编译没有错误,第二个编译有生命周期错误.

程序#1 - 编译没有错误

trait Trait<'a> {
    type T;
}

struct Impl;

impl<'a> Trait<'a> for Impl {
    type T = std::marker::PhantomData<&'a ()>;
}

struct Alpha<'a, T: Trait<'a>> {
    _dummy: std::marker::PhantomData<(&'a (), T)>,
}

fn use_alpha<'a>(_: &'a Alpha<'a, Impl>) {}

fn main() {
    for x in Vec::<Alpha<Impl>>::new().into_iter() {
        use_alpha(&x); // <-- ok
    }
}
Run Code Online (Sandbox Code Playgroud)

程序#2 - 有生命周期错误

trait Trait<'a> {
    type T;
}

struct Impl;

impl<'a> Trait<'a> for Impl {
    type T = std::marker::PhantomData<&'a ()>;
}

struct Alpha<'a, T: Trait<'a>> …
Run Code Online (Sandbox Code Playgroud)

traits lifetime rust borrowing

7
推荐指数
1
解决办法
180
查看次数

如何在处理数据流时有效地构建向量和该向量的索引?

我有一个结构Foo:

struct Foo {
    v: String,
    // Other data not important for the question
}
Run Code Online (Sandbox Code Playgroud)

我想处理数据流并将结果保存到字段中Vec<Foo>,Vec<Foo>并在字段上为此创建索引Foo::v.

我想使用a HashMap<&str, usize>作为索引,其中键将是&Foo::v,而值是该位置Vec<Foo>,但我对其他建议持开放态度.

我想尽可能快地处理数据流,这需要两次不做明显的事情.

例如,我想:

  • String每个数据流读取只分配一次
  • 不要搜索索引两次,一次检查密钥不存在,一次用于插入新密钥.
  • 不使用Rc或增加运行时间RefCell.

借用检查器不允许此代码:

let mut l = Vec::<Foo>::new();
{
    let mut hash = HashMap::<&str, usize>::new();
    //here is loop in real code, like: 
    //let mut s: String; 
    //while get_s(&mut s) {
    let s = "aaa".to_string();
    let idx: usize = match hash.entry(&s) …
Run Code Online (Sandbox Code Playgroud)

lifetime move-semantics rust borrowing

7
推荐指数
3
解决办法
936
查看次数

交换两个本地引用会导致生命周期错误

我有两个类型的变量&T,x并且y我在函数内部交换:

pub fn foo<T: Copy>(mut x: &T) {
    let y_owned = *x;
    let mut y = &y_owned;
    for _ in 0..10 {
        do_work(x, y);
        std::mem::swap(&mut x, &mut y);
    }
}

fn do_work<T>(_x: &T, _y: &T) {}
Run Code Online (Sandbox Code Playgroud)

此代码无法编译,给出以下错误:

error[E0597]: `y_owned` does not live long enough
 --> src/lib.rs:3:22
  |
3 |         let mut y = &y_owned;
  |                      ^^^^^^^ borrowed value does not live long enough
...
8 |     }
  |     - borrowed value only lives until …
Run Code Online (Sandbox Code Playgroud)

lifetime rust borrow-checker borrowing

7
推荐指数
2
解决办法
174
查看次数

借用的值在循环中存活的时间不够长

我正在尝试解析文件并Vec<Vec<&str>>从函数返回。但在推送到向量时,我在文件读取循环内遇到借用值错误。

use std::io::{self, BufReader, prelude::*};
use std::fs::File;

fn read() -> Vec<Vec<&'static str>> {
 let file = File::open("~/test").expect("failed to read file");
 let reader = BufReader::new(file);
 let mut main_vector: Vec<Vec<&str>> = Vec::new();
    for line in reader.lines() {
        match line {
            Ok(v) => {
                let mut sub_vector: Vec<&str> = Vec::new();
                for element in v.split_whitespace().collect::<Vec<&str>>() {
                    sub_vector.push(element);
                }
                main_vector.push(sub_vector);
            },
            Err(e) => panic!("failed to parse: {:?}", e),
        }
    }
    //return main_vector;
}
Run Code Online (Sandbox Code Playgroud)

这是编译器错误:

error[E0597]: `v` does not live long enough
  --> src/main.rs:67:32 …
Run Code Online (Sandbox Code Playgroud)

reference lifetime rust borrowing

7
推荐指数
1
解决办法
5289
查看次数

为什么通过 `for` 循环迭代集合被认为是 Rust 中的“移动”?

我有以下 Rust 程序。

fn main() {
    let v = vec![100, 32, 57];
    for i in v {
        println!("{}", i);
    }

    println!("{:?}", v);
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我得到:

fn main() {
    let v = vec![100, 32, 57];
    for i in v {
        println!("{}", i);
    }

    println!("{:?}", v);
}
Run Code Online (Sandbox Code Playgroud)

该错误指出在 处发生了移动for i in v。但我只是使用vlet v = vec![100, 32, 57]. 它不是像 那样的东西let v2 = v; for i in v2 ...,它将值从v移到v2。谁能帮忙解释一下?

move rust borrowing

7
推荐指数
1
解决办法
2279
查看次数

如何将字符串的 HashSet 转换为向量?

我正在尝试将 a 转换HashSet<String>为一个排序向量,然后可以join用逗号进行编辑:

use std::collections::HashSet;

fn main() {
    let mut hs = HashSet::<String>::new();
    hs.insert(String::from("fee"));
    hs.insert(String::from("fie"));
    hs.insert(String::from("foo"));
    hs.insert(String::from("fum"));

    let mut v: Vec<&String> = hs.iter().collect();
    v.sort();

    println!("{}", v.join(", "));
}
Run Code Online (Sandbox Code Playgroud)

这不会编译:

use std::collections::HashSet;

fn main() {
    let mut hs = HashSet::<String>::new();
    hs.insert(String::from("fee"));
    hs.insert(String::from("fie"));
    hs.insert(String::from("foo"));
    hs.insert(String::from("fum"));

    let mut v: Vec<&String> = hs.iter().collect();
    v.sort();

    println!("{}", v.join(", "));
}
Run Code Online (Sandbox Code Playgroud)

我明白为什么我不能加入Vec<&String>,但我怎样才能将 转换HashSet为 a Vec<String>,以便它可以加入?

在 Rust 中打印由空格分隔的迭代器的惯用方法什么?似乎并不适用,因为迭代器Args返回String值,不像迭代器HashSet返回&String …

vector hashset rust borrowing

7
推荐指数
1
解决办法
5401
查看次数

to_owned() 什么时候不克隆?

to_owned()状态的文档

从借用的数据创建拥有的数据,通常是通过克隆。

但是没有说明不会发生克隆的条件。“通常”很模糊,出于性能原因,我试图删除 clone() 调用。

有人可以澄清吗?

rust borrowing

7
推荐指数
1
解决办法
564
查看次数

为什么 Rust 会忽略 &amp;str 的生命周期检查?

fn main() {
    let strA = "a";
    let result;

    {
        let strB = "abc";
        result = longest(strA, strB); // Will return strB
    }

    println!("The longest string is {}", result); // result now point to strB!!
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
Run Code Online (Sandbox Code Playgroud)

正如我从Rust 书中得到的那样

'a将得到的混凝土的寿命等于该较小的寿命的xy

那么为什么strB现在在其范围之外可见?

lifetime ownership rust borrow-checker borrowing

7
推荐指数
1
解决办法
192
查看次数

为什么 str 主要以借用形式存在?

这是该str类型的使用方式:

let hello = "Hello, world!";

// with an explicit type annotation
let hello: &'static str = "Hello, world!";
Run Code Online (Sandbox Code Playgroud)

let hello: str = "Hello, world!"; 造成 expected `str`, found `&str`

为什么文本的默认类型str与所有原始类型、向量和String? 为什么是参考?

string types reference rust borrowing

6
推荐指数
1
解决办法
554
查看次数