Присвояване, копиране, референции

14 октомври 2025

Материал

Структури

1 2 3 4 5 6
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}
fn main() {
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}
}

Структури

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@abv.bg".to_string(),
    sign_in_count: 0,
};
fn main() {
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@abv.bg".to_string(),
    sign_in_count: 0,
};
}

Структури

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@abv.bg".to_string(),
    sign_in_count: 0,
};

println!("потребител: {} ({})", user1.first_name, user1.email);
потребител: Иван (ivancho444@abv.bg)
fn main() {
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@abv.bg".to_string(),
    sign_in_count: 0,
};

println!("потребител: {} ({})", user1.first_name, user1.email);
}

Структури

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@abv.bg".to_string(),
    sign_in_count: 0,
};

println!("{:?}", user1);
error[E0277]: `User` doesn't implement `Debug` --> src/bin/main_f19699da460375e8576d8cb60d89ab24d6d2823a.rs:16:18 | 16 | println!("{:?}", user1); | ---- ^^^^^ `User` cannot be formatted using `{:?}` because it doesn't implement `Debug` | | | required by this formatting parameter | = help: the trait `Debug` is not implemented for `User` = note: add `#[derive(Debug)]` to `User` or manually `impl Debug for User` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `User` with `#[derive(Debug)]` | 2 + #[derive(Debug)] 3 | struct User { | For more information about this error, try `rustc --explain E0277`. error: could not compile `rust` (bin "main_f19699da460375e8576d8cb60d89ab24d6d2823a") due to 1 previous error
fn main() {
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@abv.bg".to_string(),
    sign_in_count: 0,
};

println!("{:?}", user1);
}

Структури

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#[derive(Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

println!("{:?}", user1);
User { first_name: "Иван", last_name: "Иванов", email: "ivancho444@example.com", sign_in_count: 0 }
fn main() {
#[derive(Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

println!("{:?}", user1);
}

Структури

derive

1 2
#[derive(Debug)]
struct User {

Структури

1 2 3 4 5 6 7
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};
println!("{:?}", user1);
User { first_name: "Иван", last_name: "Иванов", email: "ivancho444@example.com", sign_in_count: 0 }
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};
println!("{:?}", user1);
}

Структури

1 2 3 4 5 6 7 8 9 10
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};
println!("{:?}", user1);

let user2 = user1;
println!("{:?}", user2);
User { first_name: "Иван", last_name: "Иванов", email: "ivancho444@example.com", sign_in_count: 0 } User { first_name: "Иван", last_name: "Иванов", email: "ivancho444@example.com", sign_in_count: 0 }
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};
println!("{:?}", user1);

let user2 = user1;
println!("{:?}", user2);
}

Структури

1 2 3 4 5 6 7 8 9 10 11
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;

println!("{:?}", user1);
println!("{:?}", user2);
error[E0382]: borrow of moved value: `user1` --> src/bin/main_04e624f9edc54c80710388d5f588910334224916.rs:14:18 | 5 | let user1 = User { | ----- move occurs because `user1` has type `User`, which does not implement the `Copy` trait ... 12 | let user2 = user1; | ----- value moved here 13 | 14 | println!("{:?}", user1); | ^^^^^ value borrowed here after move | note: if `User` implemented `Clone`, you could clone the value --> src/bin/main_04e624f9edc54c80710388d5f588910334224916.rs:3:1 | 3 | struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 } | ^^^^^^^^^^^ consider implementing `Clone` for this type ... 12 | let user2 = user1; | ----- you could clone this value = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` (bin "main_04e624f9edc54c80710388d5f588910334224916") due to 1 previous error
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;

println!("{:?}", user1);
println!("{:?}", user2);
}

Собственост

1 2 3 4 5 6 7 8
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

// let user2 = user1;
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

// let user2 = user1;
}

Собственост

1 2 3 4 5 6 7 8
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
}

Собственост

1 2 3 4 5 6 7 8
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
}

Собственост

1 2 3 4 5 6 7 8
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
}

Собственост

1 2 3 4 5 6 7 8
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
}

Собственост

1 2 3 4 5 6 7 8
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let user2 = user1;
}

Собственост

Преместване

Собственост

Преместване

Собственост

Преместване

Собственост

Преместване

Собственост

Преместване

Собственост

Преместване

1 2 3 4 5
let s1 = String::from("Hello");
let s2 = s1;

println!("{}", s2);
// println!("{}", s1); // грешка
Hello
fn main() {
let s1 = String::from("Hello");
let s2 = s1;

println!("{}", s2);
// println!("{}", s1); // грешка
}

Собственост

Копиране

1 2 3 4 5
let n1 = 123;
let n2 = n1;

println!("{}", n2);
println!("{}", n1);
123 123
fn main() {
let n1 = 123;
let n2 = n1;

println!("{}", n2);
println!("{}", n1);
}

Собственост

Клониране

1 2 3 4 5
let s1 = String::from("Hello");
let s2 = s1.clone();

println!("{}", s2);
println!("{}", s1);
Hello Hello
fn main() {
let s1 = String::from("Hello");
let s2 = s1.clone();

println!("{}", s2);
println!("{}", s1);
}

Собственост

Клониране

1 2 3 4 5 6
let s1 = String::from("Hello");
let mut s2 = s1.clone();
s2.push_str(", room");

println!("{}", s2);
println!("{}", s1);
Hello, room Hello
fn main() {
let s1 = String::from("Hello");
let mut s2 = s1.clone();
s2.push_str(", room");

println!("{}", s2);
println!("{}", s1);
}

Собственост

Клониране

1 2 3 4 5 6 7 8 9 10 11 12 13
#[derive(Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    /* ... */
};

let user2 = user1.clone();
error[E0599]: no method named `clone` found for struct `User` in the current scope --> src/bin/main_969abe399b5aeac08a21f49af489d9cf76a659f1.rs:18:19 | 3 | struct User { | ----------- method `clone` not found for this struct ... 18 | let user2 = user1.clone(); | ^^^^^ method not found in `User` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `Clone` For more information about this error, try `rustc --explain E0599`. error: could not compile `rust` (bin "main_969abe399b5aeac08a21f49af489d9cf76a659f1") due to 1 previous error
fn main() {
#[derive(Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let user2 = user1.clone();
}

Собственост

Клониране

1 2 3 4 5 6 7 8 9 10 11 12 13 14
#[derive(Clone)]
#[derive(Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    /* ... */
};

let user2 = user1.clone();
fn main() {
#[derive(Clone)]
#[derive(Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let user2 = user1.clone();
}

Собственост

Клониране

1 2 3 4 5 6 7 8 9 10 11 12 13
#[derive(Clone, Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    /* ... */
};

let user2 = user1.clone();
fn main() {
#[derive(Clone, Debug)]
struct User {
    first_name: String,
    last_name: String,
    email: String,
    sign_in_count: u32,
}

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let user2 = user1.clone();
}

Собственост

Частично преместване

1 2 3 4 5 6 7 8 9 10 11 12
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let first_name = user1.first_name;
let last_name = user1.last_name;

println!("{} {}", first_name, last_name);
println!("{}", user1.email);
Иван Иванов ivancho444@example.com
fn main() {
#[derive(Clone, Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32, }

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let first_name = user1.first_name;
let last_name = user1.last_name;

println!("{} {}", first_name, last_name);
println!("{}", user1.email);
}

Собственост

Частично преместване

1 2 3 4 5 6 7 8 9 10 11 12
let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let first_name = user1.first_name;
let last_name = user1.last_name;

println!("{} {}", first_name, last_name);
println!("{:?}", user1);
error[E0382]: borrow of partially moved value: `user1` --> src/bin/main_89121857f23d6145b09a167ad215fc546cb6cfee.rs:16:18 | 13 | let last_name = user1.last_name; | --------------- value partially moved here ... 16 | println!("{:?}", user1); | ^^^^^ value borrowed here after partial move | = note: partial move occurs because `user1.last_name` has type `String`, which does not implement the `Copy` trait = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` (bin "main_89121857f23d6145b09a167ad215fc546cb6cfee") due to 1 previous error
fn main() {
#[derive(Clone, Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32, }

let user1 = User {
    first_name: "Иван".to_string(),
    last_name: "Иванов".to_string(),
    email: "ivancho444@example.com".to_string(),
    sign_in_count: 0,
};

let first_name = user1.first_name;
let last_name = user1.last_name;

println!("{} {}", first_name, last_name);
println!("{:?}", user1);
}

При функции

При функции

1 2 3 4 5 6 7 8 9 10
fn print_user(user: User) {
    println!("{:?}", user);
}

let user1 = User {
    /* ... */
};

print_user(user1);
// print_user(user1);
User { first_name: "Иван", last_name: "Иванов", email: "ivancho444@example.com", sign_in_count: 0 }
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn print_user(user: User) {
    println!("{:?}", user);
}

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

print_user(user1);
// print_user(user1);
}

При функции

1 2 3 4 5 6 7 8 9 10
fn print_user(user: User) {
    println!("{:?}", user);
}

let user1 = User {
    /* ... */
};

print_user(user1);
print_user(user1);
error[E0382]: use of moved value: `user1` --> src/bin/main_077f47614989244065d75a10ea5b7057f3c5819e.rs:18:12 | 9 | let user1 = User { | ----- move occurs because `user1` has type `User`, which does not implement the `Copy` trait ... 17 | print_user(user1); | ----- value moved here 18 | print_user(user1); | ^^^^^ value used here after move | note: consider changing this parameter type in function `print_user` to borrow instead if owning the value isn't necessary --> src/bin/main_077f47614989244065d75a10ea5b7057f3c5819e.rs:5:21 | 5 | fn print_user(user: User) { | ---------- ^^^^ this parameter takes ownership of the value | | | in this function note: if `User` implemented `Clone`, you could clone the value --> src/bin/main_077f47614989244065d75a10ea5b7057f3c5819e.rs:3:1 | 3 | struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 } | ^^^^^^^^^^^ consider implementing `Clone` for this type ... 17 | print_user(user1); | ----- you could clone this value For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` (bin "main_077f47614989244065d75a10ea5b7057f3c5819e") due to 1 previous error
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn print_user(user: User) {
    println!("{:?}", user);
}

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

print_user(user1);
print_user(user1);
}

Референции

Референции

Референции

1 2 3 4 5 6 7 8 9 10
fn print_user(user: &User) {
    println!("потребител {} (влизания {})", user.email, user.sign_in_count);
}

let user1 = User {
    /* ... */
};

print_user(&user1);
print_user(&user1);
потребител ivancho444@example.com (влизания 0) потребител ivancho444@example.com (влизания 0)
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn print_user(user: &User) {
    println!("потребител {} (влизания {})", user.email, user.sign_in_count);
}

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

print_user(&user1);
print_user(&user1);
}

Референции

1 2 3 4 5 6 7 8 9 10 11
fn print_user(user: &User) {
    println!("потребител {} (влизания {})", user.email, user.sign_in_count);
}

let user1 = User {
    /* ... */
};

let user_ref = &user1;
print_user(user_ref);
print_user(user_ref);
потребител ivancho444@example.com (влизания 0) потребител ivancho444@example.com (влизания 0)
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn print_user(user: &User) {
    println!("потребител {} (влизания {})", user.email, user.sign_in_count);
}

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let user_ref = &user1;
print_user(user_ref);
print_user(user_ref);
}

Референции

1 2 3
user_ref.email
// еквивалентно на
(*user_ref).email

Референции

1
user_ref.email  // : String

Референции

1
user_ref.email  // : String
1 2 3 4 5 6
let user1 = User {
    /* ... */
};

let user_ref = &user1;
let email = user_ref.email;
error[E0507]: cannot move out of `user_ref.email` which is behind a shared reference --> src/bin/main_3cf3e95d06a467eb0d102ad03ce84f1b8be04798.rs:14:13 | 14 | let email = user_ref.email; | ^^^^^^^^^^^^^^ move occurs because `user_ref.email` has type `String`, which does not implement the `Copy` trait | help: consider borrowing here | 14 | let email = &user_ref.email; | + help: consider cloning the value if the performance cost is acceptable | 14 | let email = user_ref.email.clone(); | ++++++++ For more information about this error, try `rustc --explain E0507`. error: could not compile `rust` (bin "main_3cf3e95d06a467eb0d102ad03ce84f1b8be04798") due to 1 previous error
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let user_ref = &user1;
let email = user_ref.email;
}

Референции

1
&user_ref.email  // : &String
1 2 3 4 5 6 7 8
let user1 = User {
    /* ... */
};

let email = &user1.email;

println!("{:?}", user1);
println!("{:?}", email);
User { first_name: "Иван", last_name: "Иванов", email: "ivancho444@example.com", sign_in_count: 0 } "ivancho444@example.com"
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

let user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let email = &user1.email;

println!("{:?}", user1);
println!("{:?}", email);
}

Референции

Референции

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
fn check_and_sign_in(user: &mut User, email: &str) -> bool {
    if user.email == email {
        user.sign_in_count += 1;
        true
    } else {
        false
    }
}

let mut user1 = User {
    /* ... */
};

print_user(&user1);
check_and_sign_in(&mut user1, "ivancho444@example.com");
print_user(&user1);
потребител ivancho444@example.com (влизания 0) потребител ivancho444@example.com (влизания 1)
fn main() {
#[derive(Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }
fn print_user(user: &User) { println!("потребител {} (влизания {})", user.email, user.sign_in_count); }

fn check_and_sign_in(user: &mut User, email: &str) -> bool {
    if user.email == email {
        user.sign_in_count += 1;
        true
    } else {
        false
    }
}

let mut user1 = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

print_user(&user1);
check_and_sign_in(&mut user1, "ivancho444@example.com");
print_user(&user1);
}

Валидност

Валидност

Валидност

Валидност

Валидност

1 2 3 4 5 6 7
fn main() {
    let user1 = User { /* ... */ };
    let user2 = User { /* ... */ };

} // <--+
  //    | - user2 се унищожава (извиква се деструктора)
  //    | - после user1 се унищожава

Валидност

1 2 3 4 5 6 7 8
fn main() {
    let user1 = User { /* ... */ };
    {
        let user2 = User { /* ... */ };
    } // <--+
      //    | - user2 се унищожава
} // <--+
  //    | - user1 се унищожава

Валидност

1 2 3 4 5 6 7 8
fn main() {
    let user1 = User { /* ... */ };

    {
        let user_ref = &user1;
    } // <--+
      //    | OK - user_ref се "унищожава" преди user1
}

Валидност

1 2 3 4 5
fn main() {
    let user1 = User { /* ... */ };
    let user_ref = &user1;
}  // <--+
   //    | OK - user_ref се "унищожава" преди user1

Валидност

1 2 3 4 5 6 7 8
fn main() {
    let user_ref = {
        let user1 = User { /* ... */ };

        &user1
    }; // <--+
       //    | грешка - user1 се унищожава преди user_ref
}

Валидност

1 2 3 4 5 6 7 8 9 10
fn make_user() -> &User {
    let user = User {
        first_name: "Иван".to_string(),
        last_name: "Иванов".to_string(),
        email: "ivancho444@example.com".to_string(),
        sign_in_count: 0,
    };

    &user
}
error[E0106]: missing lifetime specifier --> src/bin/main_4a0106a2a87805b208db2b98da049f46c9c82709.rs:4:19 | 4 | fn make_user() -> &User { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | 4 | fn make_user() -> &'static User { | +++++++ help: instead, you are more likely to want to return an owned value | 4 - fn make_user() -> &User { 4 + fn make_user() -> User { | For more information about this error, try `rustc --explain E0106`. error: could not compile `rust` (bin "main_4a0106a2a87805b208db2b98da049f46c9c82709") due to 1 previous error
fn main() {}
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn make_user() -> &User {
    let user = User {
        first_name: "Иван".to_string(),
        last_name: "Иванов".to_string(),
        email: "ivancho444@example.com".to_string(),
        sign_in_count: 0,
    };

    &user
}

Валидност

1 2 3 4 5 6 7 8 9 10
let user = User {
    /* ... */
};

let user_ref = &user;

// преместване от `user`
let new_user = user;

println!("{:?}", user_ref);
error[E0505]: cannot move out of `user` because it is borrowed --> src/bin/main_f4df860c7064493f3f5268cabeb09dd34b55a345.rs:16:16 | 5 | let user = User { | ---- binding `user` declared here ... 13 | let user_ref = &user; | ----- borrow of `user` occurs here ... 16 | let new_user = user; | ^^^^ move out of `user` occurs here 17 | 18 | println!("{:?}", user_ref); | -------- borrow later used here | help: consider cloning the value if the performance cost is acceptable | 13 | let user_ref = &user.clone(); | ++++++++ For more information about this error, try `rustc --explain E0505`. error: could not compile `rust` (bin "main_f4df860c7064493f3f5268cabeb09dd34b55a345") due to 1 previous error
#[derive(Clone, Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn main() {
let user = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let user_ref = &user;

// преместване от `user`
let new_user = user;

println!("{:?}", user_ref);
}

Валидност

Non lexical lifetimes

1 2 3 4 5 6 7 8 9 10
let user = User {
    /* ... */
};

let user_ref = &user;

// преместване от `user`
let new_user = user;

// println!("{:?}", user_ref);
#[derive(Clone, Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn main() {
let user = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

let user_ref = &user;

// преместване от `user`
let new_user = user;

// println!("{:?}", user_ref);
}

Валидност

Non lexical lifetimes

1 2 3 4 5 6 7 8 9 10 11 12
let user = User {
    /* ... */
};

{
    let user_ref = &user;
}

// преместване от `user`
let new_user = user;

// println!("{:?}", user_ref);
#[derive(Clone, Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn main() {
let user = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

{
    let user_ref = &user;
}

// преместване от `user`
let new_user = user;

// println!("{:?}", user_ref);
}

Валидност

Non lexical lifetimes

1 2 3 4 5 6 7 8 9 10 11 12
let user = User {
    /* ... */
};

{
    let user_ref = &user;

    // преместване от `user`
    let new_user = user;

    println!("{:?}", user_ref);
}
error[E0505]: cannot move out of `user` because it is borrowed --> src/bin/main_c2978216bc64735f29a51f1c97dcd28468a61c4e.rs:17:20 | 5 | let user = User { | ---- binding `user` declared here ... 14 | let user_ref = &user; | ----- borrow of `user` occurs here ... 17 | let new_user = user; | ^^^^ move out of `user` occurs here 18 | 19 | println!("{:?}", user_ref); | -------- borrow later used here | help: consider cloning the value if the performance cost is acceptable | 14 | let user_ref = &user.clone(); | ++++++++ For more information about this error, try `rustc --explain E0505`. error: could not compile `rust` (bin "main_c2978216bc64735f29a51f1c97dcd28468a61c4e") due to 1 previous error
#[derive(Clone, Debug)]
struct User { first_name: String, last_name: String, email: String, sign_in_count: u32 }

fn main() {
let user = User {
    /* ... */
first_name: "Иван".to_string(),
last_name: "Иванов".to_string(),
email: "ivancho444@example.com".to_string(),
sign_in_count: 0,
};

{
    let user_ref = &user;

    // преместване от `user`
    let new_user = user;

    println!("{:?}", user_ref);
}
}

Borrow checker

Borrow checker

Правило

Borrow checker

Правило

Borrow checker

Правило

Borrow checker

Защо?

Borrow checker

Защо?

Borrow checker

Защо?

Borrow checker

Защо?

Borrow checker

Защо?

Borrow checker

Защо?

Borrow checker

Цитат

Monads are a clever way to show you can program without mutation;
[Rust borrow rules] are an even cleverer way to show you can just use mutation

Borrow checker

Пример

Класически пример от C++ - инвалидация на итератори

1 2 3 4 5 6 7 8 9
let mut vec = vec![1, 2, 3];

for val in vec.iter() {
    do_something(val);

    if some_condition {
        vec.push(99);
    }
}
error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable --> src/bin/main_9036c0a5609ad39a3ebd2868f8e68cf6133e5a72.rs:10:9 | 6 | for val in vec.iter() { | ---------- | | | immutable borrow occurs here | immutable borrow later used here ... 10 | vec.push(99); | ^^^^^^^^^^^^ mutable borrow occurs here For more information about this error, try `rustc --explain E0502`. error: could not compile `rust` (bin "main_9036c0a5609ad39a3ebd2868f8e68cf6133e5a72") due to 1 previous error
fn main() {
fn do_something(_: &i32) {}
let some_condition = false;
let mut vec = vec![1, 2, 3];

for val in vec.iter() {
    do_something(val);

    if some_condition {
        vec.push(99);
    }
}
}

Низове

Низове

String

Низове

Разполагане в паметта (String)

1
let my_name = String::from("Pascal Precht");
fn main() {
let my_name = String::from("Pascal Precht");
}



            [––––– my_name: String ––––]
            +––––––––+––––––––+––––––––+
stack frame │ ptr=•  │ cap=16 │ len=13 │
            +–––––│––+––––––––+––––––––+
              +–––+
              │
              │
            [–│–––––––––––––––––– ptr + len ––––––––––––––––––––]
            [-│------------------ ptr + cap --------------------------------]
            +–V–+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+
       heap │ P │ a │ s │ c │ a │ l │ ␣ │ P │ r │ e │ c │ h │ t │   │   │   │
            +–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+

Низове

String

1 2 3 4 5 6
let mut hello = String::from("Hello, ");

hello.push('w');
hello.push_str("orld!");

println!("{:?}", hello);
"Hello, world!"
fn main() {
let mut hello = String::from("Hello, ");

hello.push('w');
hello.push_str("orld!");

println!("{:?}", hello);
}

Низове

&str

Низове

Разполагане в паметта (&str)

1 2
let my_name = String::from("Pascal Precht");
let my_name_slice = my_name.as_str();
fn main() {
let my_name = String::from("Pascal Precht");
let my_name_slice = my_name.as_str();
}


            [––––– my_name: String ––––]  [my_name_slice: &str]
            +––––––––+––––––––+––––––––+  +–––––––––+–––––––––+
stack frame │ ptr=•  │ cap=16 │ len=13 │  │  ptr=•  │  len=13 │
            +–––––│––+––––––––+––––––––+  +––––––│––+–––––––––+
             +––––+                              │
             │ +–––––––––––––––––––––––––––––––––+
             │ │
             │ │
            [│–│––––––––––––––––––––– str ––––––––––––––––––––––]
            +V–V+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+
       heap │ P │ a │ s │ c │ a │ l │ ␣ │ P │ r │ e │ c │ h │ t │   │   │   │
            +–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+

Низове

&str

Низове

&str

Низове

Литерали

1
let s: &str = "literal string";

Низове

Литерали

1
let s: &str = "literal string";

Низове

Литерали

1
let s: &str = "literal string";
1
let s: &'static str = "Hello";

Низове

Резени

1 2 3 4 5 6 7
let s = "Hello, world";
let hello = &s[0..5];
let world = &s[7..12];

println!("{:?}", s);
println!("{:?}", hello);
println!("{:?}", world);
"Hello, world" "Hello" "world"
fn main() {
let s = "Hello, world";
let hello = &s[0..5];
let world = &s[7..12];

println!("{:?}", s);
println!("{:?}", hello);
println!("{:?}", world);
}

Низове

Резени

1 2 3 4 5 6 7
let s = "Hello, world";
let hello = &s[0..5];
let world = &s[7..12];

println!("{:12}: ptr={:#x} len={}", s, s.as_ptr() as usize, s.len());
println!("{:12}: ptr={:#x} len={}", hello, hello.as_ptr() as usize, hello.len());
println!("{:12}: ptr={:#x} len={}", world, world.as_ptr() as usize, world.len());
Hello, world: ptr=0x556339750c0b len=12 Hello : ptr=0x556339750c0b len=5 world : ptr=0x556339750c12 len=5
fn main() {
let s = "Hello, world";
let hello = &s[0..5];
let world = &s[7..12];

println!("{:12}: ptr={:#x} len={}", s, s.as_ptr() as usize, s.len());
println!("{:12}: ptr={:#x} len={}", hello, hello.as_ptr() as usize, hello.len());
println!("{:12}: ptr={:#x} len={}", world, world.as_ptr() as usize, world.len());
}

Низове

Разполагане в паметта (&str)

1 2
let my_name = "Pascal Precht";
let last_name = &my_name[7..];
fn main() {
let my_name = "Pascal Precht";
let last_name = &my_name[7..];
}


            [– my_name: &str –]           [last_name: &str]
            +––––––––+––––––––+           +–––––––+–––––––+
stack frame │ ptr=•  │ len=13 │           │ ptr=• │ len=6 │
            +–––––│––+––––––––+           +–––––│–+–––––––+
              +–––+                             │
              │                           +–––––+
              │                           │
              │                           │
              │                         [–│––––––– str –––––––––]
            +–V–+–––+–––+–––+–––+–––+–––+–V–+–––+–––+–––+–––+–––+
    .rodata │ P │ a │ s │ c │ a │ l │ ␣ │ P │ r │ e │ c │ h │ t │
            +–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+–––+

Низове

Интервали

Низове

Интервали

Низове

Интервали

Низове

Интервали

1 2 3 4 5 6 7 8 9 10
let s = String::from("hello, world");

let r1 = &s[1..4];
println!("{}", r1);

let r2 = &s[..s.len()-2]; // &s[..-2] не е възможно
println!("{}", r2);

let r3 = &s[..];
println!("{}", r3);
ell hello, wor hello, world
fn main() {
let s = String::from("hello, world");

let r1 = &s[1..4];
println!("{}", r1);

let r2 = &s[..s.len()-2]; // &s[..-2] не е възможно
println!("{}", r2);

let r3 = &s[..];
println!("{}", r3);
}

Низове

Използване

Кога да използвате String?

1 2 3 4 5
struct User {
    first_name: String,
    last_name: String,
    email: String,
}

Низове

Използване

Кога да използвате &str?

1
fn print_names(first: &str, last: &str) { /* ... */ }
1
fn trim_whitespace(s: &str) -> &str { /* ... */ }

Низове

Използване

1 2 3 4 5
let hello = "hello";

let hello2 = format!("{}, again", hello); // : String

println!("{:?}", hello2);
"hello, again"
fn main() {
let hello = "hello";

let hello2 = format!("{}, again", hello); // : String

println!("{:?}", hello2);
}

Низове

Използване

1 2 3 4 5 6 7 8
// конвертиране от &str до String
let s = String::from("hello");
let s = "hello".to_string();
let s = "hello".to_owned();

// конвертиране от String до &str
let str_ref = s.as_str();
let str_ref = &s[..];
fn main() {
// конвертиране от &str до String
let s = String::from("hello");
let s = "hello".to_string();
let s = "hello".to_owned();

// конвертиране от String до &str
let str_ref = s.as_str();
let str_ref = &s[..];
}

Низове

Индексиране

1 2 3 4 5
let hello = "Здравей свят";

println!("bytes {}", hello.len());
println!("chars {}", hello.chars().count());
println!("{:?}", &hello[..14]);
bytes 23 chars 12 "Здравей"
fn main() {
let hello = "Здравей свят";

println!("bytes {}", hello.len());
println!("chars {}", hello.chars().count());
println!("{:?}", &hello[..14]);
}

Низове

Индексиране

1 2 3
let hello = "Здравей свят";

println!("{:?}", &hello[..13]);
thread 'main' panicked at src/bin/main_3b57e62b952095839146965c2229e9511f8e078c.rs:4:24: byte index 13 is not a char boundary; it is inside 'й' (bytes 12..14) of `Здравей свят` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fn main() {
let hello = "Здравей свят";

println!("{:?}", &hello[..13]);
}

Низове

Индексиране

1 2 3
let hello = "Здравей свят";

println!("{:?}", hello[2]);
error[E0277]: the type `str` cannot be indexed by `{integer}` --> src/bin/main_07697788709a48545e5e9b9d2fbc0083c5254bc1.rs:4:24 | 4 | println!("{:?}", hello[2]); | ^ string indices are ranges of `usize` | = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> = help: the following other types implement trait `SliceIndex<T>`: `usize` implements `SliceIndex<ByteStr>` `usize` implements `SliceIndex<[T]>` = note: required for `str` to implement `Index<{integer}>` For more information about this error, try `rustc --explain E0277`. error: could not compile `rust` (bin "main_07697788709a48545e5e9b9d2fbc0083c5254bc1") due to 1 previous error
fn main() {
let hello = "Здравей свят";

println!("{:?}", hello[2]);
}

Масиви

Масиви

Типа [T;N]

1 2
let point_coords = [1.0, 3.5, 0.0];  // тип [f32; 3]
println!("{:?}", point_coords);
[1.0, 3.5, 0.0]
fn main() {
let point_coords = [1.0, 3.5, 0.0];  // тип [f32; 3]
println!("{:?}", point_coords);
}

Масиви

Типа [T;N]

1 2
let zero = [0.0; 3];    // тип [f32; 3]
println!("{:?}", zero);
[0.0, 0.0, 0.0]
fn main() {
let zero = [0.0; 3];    // тип [f32; 3]
println!("{:?}", zero);
}

Масиви

Tипа Vec<T>

1 2 3 4 5 6
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);

println!("{:?}", v);
[1, 2, 3]
fn main() {
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);

println!("{:?}", v);
}

Масиви

Типа Vec<T>

1 2 3
let v = vec![1, 2, 3];

println!("{:?}", v);
[1, 2, 3]
fn main() {
let v = vec![1, 2, 3];

println!("{:?}", v);
}

Масиви

Типа Vec<T>

1 2 3
let v = vec![0; 8];

println!("{:?}", v);
[0, 0, 0, 0, 0, 0, 0, 0]
fn main() {
let v = vec![0; 8];

println!("{:?}", v);
}

Масиви

Типа &[T]

Масиви

Типа &[T]

Масиви

Типа &[T]

Масиви

Типа &[T]

Масиви

Резени

1 2 3 4 5 6 7
let arr = [2, 4, 6, 8, 10];
let arr_slice = &arr[1..4];     // тип &[i32]
println!("{:?}", arr_slice);

let v = vec![2, 4, 6, 8, 10];
let vec_slice = &v[1..4];       // тип &[i32]
println!("{:?}", vec_slice);
[4, 6, 8] [4, 6, 8]
fn main() {
let arr = [2, 4, 6, 8, 10];
let arr_slice = &arr[1..4];     // тип &[i32]
println!("{:?}", arr_slice);

let v = vec![2, 4, 6, 8, 10];
let vec_slice = &v[1..4];       // тип &[i32]
println!("{:?}", vec_slice);
}

Масиви

Литерали

1 2 3
let slice = &[2, 4, 6, 8, 10];

println!("{:?}", slice);
[2, 4, 6, 8, 10]
fn main() {
let slice = &[2, 4, 6, 8, 10];

println!("{:?}", slice);
}

Масиви

Мутация

1 2 3 4 5 6 7
let mut v = vec![2, 4, 6, 8, 10, 12];

for elem in &mut v[1..4] {
    *elem += 1;
}

println!("{:?}", v);
[2, 5, 7, 9, 10, 12]
fn main() {
let mut v = vec![2, 4, 6, 8, 10, 12];

for elem in &mut v[1..4] {
    *elem += 1;
}

println!("{:?}", v);
}

Обобщение

Масив Низ
статичен [T; N] - собственост над стойността
динамичен Vec<T> String собственост над стойността
резен &[T] &str заета назаем стойност (borrow)
mutable резен &mut [T] &mut str заета назаем стойност (borrow)

Въпроси