diff --git a/ChangeLog.md b/ChangeLog.md index e49816a..b8a6aba 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,7 +3,9 @@ ### 2022-03-29 - Add language switch icon in top-right corner - +- Add [&'static and T: 'static](https://practice.rs/lifetime/static.html) + + ### 2022-03-28 - Add [Basic lifetime](https://practice.rs/lifetime/basic.html) diff --git a/en/src/SUMMARY.md b/en/src/SUMMARY.md index a7fa3bc..3852591 100644 --- a/en/src/SUMMARY.md +++ b/en/src/SUMMARY.md @@ -51,7 +51,7 @@ - [formating](formatted-output/formatting.md) - [Lifetime](lifetime/intro.md) - [basic](lifetime/basic.md) - - [&'static and T: 'static TODO](lifetime/static.md) + - [&'static and T: 'static](lifetime/static.md) - [advance TODO](lifetime/advance.md) - [Functional programing TODO](functional-programing/intro.md) - [Closure](functional-programing/cloure.md) diff --git a/en/src/lifetime/static.md b/en/src/lifetime/static.md index 782446e..7eac7e1 100644 --- a/en/src/lifetime/static.md +++ b/en/src/lifetime/static.md @@ -1,5 +1,151 @@ # &'static and T: 'static +`'static` is a reserverd lifetime name, you might have encountered it serveral times: +```rust +// A reference with 'static lifetime: +let s: &'static str = "hello world"; +// 'static as part of a trait bound: +fn generic(x: T) where T: 'static {} +``` + +Though they are all `'static`, but subtly different. + +## &'static +As a reference lifetime, `&'static` indicates the data pointed to by the reference lives as long as the running program. But it can still be coerced to a shorter lifetime. + + + +1γ€πŸŒŸπŸŒŸ There are several ways to make a variable with `'static` lifetime, two of them are stored in the read-only memory of the binary。 + +```rust,editable + +/* Fill in the blank in two ways */ +fn main() { + __; + need_static(v); + + println!("Success!") +} + +fn need_static(r : &'static str) { + assert_eq!(r, "hello"); +} +``` + +2、 🌟🌟🌟🌟 Another way to make `'static` lifetime is using `Box::leak` +```rust,editable +#[derive(Debug)] +struct Config { + a: String, + b: String, +} +static mut config: Option<&mut Config> = None; + +/* Make it work without changing the function signatures of `init`*/ +fn init() -> Option<&'static mut Config> { + Some(&mut Config { + a: "A".to_string(), + b: "B".to_string(), + }) +} + + +fn main() { + unsafe { + config = init(); + + println!("{:?}",config) + } +} +``` + +3、 🌟 `&'static` only indicates that the data can live forever, not the reference. The latter one will be constrained by its scope. +```rust,editable +fn main() { + { + // Make a `string` literal and print it: + let static_string = "I'm in read-only memory"; + println!("static_string: {}", static_string); + + // When `static_string` goes out of scope, the reference + // can no longer be used, but the data remains in the binary. + } + + println!("static_string reference remains alive: {}", static_string); +} +``` + +4、 `&'static` can be coerced to a shorter lifetime. + +**Example** +```rust,editable +// Make a constant with `'static` lifetime. +static NUM: i32 = 18; + +// Returns a reference to `NUM` where its `'static` +// lifetime is coerced to that of the input argument. +fn coerce_static<'a>(_: &'a i32) -> &'a i32 { + &NUM +} + +fn main() { + { + // Make an integer to use for `coerce_static`: + let lifetime_num = 9; + + // Coerce `NUM` to lifetime of `lifetime_num`: + let coerced_static = coerce_static(&lifetime_num); + + println!("coerced_static: {}", coerced_static); + } + + println!("NUM: {} stays accessible!", NUM); +} +``` + + + +## T: 'static +As a trait bound, it means the type does not contain any non-static references. Eg. the receiver can hold on to the type for as long as they want and it will never become invalid until they drop it. + +It's important to understand this means that any owned data always passes a `'static `lifetime bound, but a reference to that owned data generally does no。 + +5γ€πŸŒŸπŸŒŸ +```rust,editable +/* Make it work */ +use std::fmt::Debug; + +fn print_it( input: T) { + println!( "'static value passed in is: {:?}", input ); +} + +fn print_it1( input: impl Debug + 'static ) { + println!( "'static value passed in is: {:?}", input ); +} + + +fn print_it2( input: &T) { + println!( "'static value passed in is: {:?}", input ); +} + +fn main() { + // i is owned and contains no references, thus it's 'static: + let i = 5; + print_it(i); + + // oops, &i only has the lifetime defined by the scope of + // main(), so it's not 'static: + print_it(&i); + + print_it1(&i); + + // but this one WORKS ! + print_it2(&i); +} +``` + + +6γ€πŸŒŸπŸŒŸπŸŒŸ ```rust,editable use std::fmt::Display; diff --git a/solutions/lifetime/static.md b/solutions/lifetime/static.md new file mode 100644 index 0000000..dec108e --- /dev/null +++ b/solutions/lifetime/static.md @@ -0,0 +1,98 @@ +1、 +```rust +fn main() { + let v: &str = "hello"; + need_static(v); + + println!("Success!") +} + +fn need_static(r : &'static str) { + assert_eq!(r, "hello"); +} +``` + +```rust +fn main() { + const v: &str = "hello"; + need_static(v); + + println!("Success!") +} + +fn need_static(r : &'static str) { + assert_eq!(r, "hello"); +} +``` + +2、 +```rust +#[derive(Debug)] +struct Config { + a: String, + b: String, +} +static mut config: Option<&mut Config> = None; + +fn init() -> Option<&'static mut Config> { + let c = Box::new(Config { + a: "A".to_string(), + b: "B".to_string(), + }); + + Some(Box::leak(c)) +} + + +fn main() { + unsafe { + config = init(); + + println!("{:?}",config) + } +} +``` + +3、 +```rust +fn main() { + // Make a `string` literal and print it: + let static_string = "I'm in read-only memory"; + println!("static_string: {}", static_string); + + println!("static_string reference remains alive: {}", static_string); +} +``` + +5、 +```rust +use std::fmt::Debug; + +fn print_it( input: T) { + println!( "'static value passed in is: {:?}", input ); +} + +fn print_it1( input: impl Debug + 'static ) { + println!( "'static value passed in is: {:?}", input ); +} + + +fn print_it2( input: &T) { + println!( "'static value passed in is: {:?}", input ); +} + +fn main() { + // i is owned and contains no references, thus it's 'static: + const i:i32 = 5; + print_it(i); + + // oops, &i only has the lifetime defined by the scope of + // main(), so it's not 'static: + print_it(&i); + + print_it1(&i); + + // but this one WORKS ! + print_it2(&i); +} +``` diff --git a/zh-CN/.DS_Store b/zh-CN/.DS_Store index bf66362..ff91dd3 100644 Binary files a/zh-CN/.DS_Store and b/zh-CN/.DS_Store differ