Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Practice] 该段代码为什么会通过? #3

Open
ZhangHanDong opened this issue Oct 28, 2017 · 2 comments
Open

[Practice] 该段代码为什么会通过? #3

ZhangHanDong opened this issue Oct 28, 2017 · 2 comments

Comments

@ZhangHanDong
Copy link
Contributor

Rust Nightly 1.22.0

use std::collections::BTreeMap;

fn foo(_qux: &BTreeMap<&'static str, &'static str>) -> Option<String> {
    Some("baz".to_owned())
}

fn main() {
    let mut map = BTreeMap::new();
    map.insert("foo", "bar");
    foo(&map).and_then( |baz| {
        let mut map = map;
        map.insert("sign", &baz);
        Some(())
    });
}

如果注释掉 let mut map = map; ,为什么会报错?

@ZhangHanDong ZhangHanDong changed the title 该段代码为什么会通过? [Practice] 该段代码为什么会通过? Oct 28, 2017
@ZhangHanDong
Copy link
Contributor Author

相关issue: rust-lang/rust#45587

@huangjj27
Copy link

huangjj27 commented Feb 6, 2018

当去掉let语句之后产生了如下的语义:

  1. rustc推断在main中声明的mapK, V是具有'static lifetime, 理由是foo函数接受了map作为参数;
  2. foo返回的Some是to_owned的关系, 所以变量baz会被move到闭包之中, 于是其析构也会提前到闭包调用结束, baz的生命周期为整个闭包调用

因此baz的声明周期没有'static长, 所以报错:

 error[E0597]: `baz` does not live long enough
  --> test.rs:12:29
   |
12 |         map.insert("sign", &baz);
   |                             ^^^ borrowed value does not live long enough
13 |         Some(())
14 |     });
   |     - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

而当我们保留了let语句是, 相当于把mapmove到了闭包中, 并且在let语句的时候重新推断了生命周期条件:

// let dist_map: BTreeMap(&'static str, &'a str) = moved_map;
let map = map;

而这种推断是合理的, 因为'static生命周期要比任何生命周期'a'要长('static: 'a);

接着, rust再推断出满足'a lifetime的最小lifetime 要比&baz的lifetime要长('a: 'baz), 所有生命周期参数得以满足, 于是通过了编译.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants