Skip to content

Instantly share code, notes, and snippets.

@xpepper
Last active April 19, 2024 21:53
Show Gist options
  • Save xpepper/0f990d8f5998aae8070be09a846f414b to your computer and use it in GitHub Desktop.
Save xpepper/0f990d8f5998aae8070be09a846f414b to your computer and use it in GitHub Desktop.
practicing ownership and borrowing (perplexity.ai)

Here are some Rust code examples that involve ownership and borrowing. For each example, determine whether it will compile and explain why or why not based on Rust's ownership and borrowing rules.

Example 1

fn main() {
    let s1 = String::from("hello");
    let s2 = &s1;
    drop(s1);
    println!("s2 says: {}", s2);
}

Explanation: This example tests understanding of borrowing and the drop function.

Example 2

fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    s.push_str(", world!");
    println!("{} and {}", r1, r2);
}

Explanation: This example is about mutable and immutable references coexisting.

Example 3

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

Explanation: This example involves cloning and how it affects ownership and borrowing.

Example 4

fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &s;
    println!("{}, {}", r1, r2);
}

Explanation: This example checks the rules regarding mutable and immutable references.

Example 5

fn main() {
    let s1 = String::from("hello");
    takes_ownership(s1);
    println!("s1 is still accessible: {}", s1);
}

fn takes_ownership(some_string: String) {
    println!("{}", some_string);
}

Explanation: This example tests the basic understanding of ownership transfer to a function.

Example 6

fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &mut s;
    println!("{}, {}", r1, r2);
}

Explanation: This example tests mutable and immutable references in the same scope.

Example 7

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;
    let s3 = s2;
    println!("{}", s1);
}

Explanation: This example demonstrates ownership transfer between variables.

Example 8

fn main() {
    let s = String::from("hello");
    let s_ref = &s;
    drop(s);
    println!("s_ref: {}", s_ref);
}

Explanation: This example involves the drop function and a reference to the dropped value.

Example 9

fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    s.clear();
    println!("r1: {}, r2: {}", r1, r2);
}

Explanation: This example checks for modification of a borrowed value.

Example 10

fn main() {
    let s1 = gives_ownership();
    let s2 = String::from("hello");
    let s3 = takes_and_gives_back(s2);
    println!("{}, {}", s1, s3);
}

fn gives_ownership() -> String {
    let some_string = String::from("yours");
    some_string
}

fn takes_and_gives_back(a_string: String) -> String {
    a_string
}

Explanation: This example demonstrates function return values and ownership transfer.

Example 11

fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &mut s;
    r1.push_str(", world");
    println!("{}", r2);
}

Explanation: This example tests multiple mutable references to the same value.

Example 12

fn main() {
    let s1 = String::from("hello");
    let s2 = &s1;
    let s3 = &s1;
    println!("{}, {}, and {}", s1, s2, s3);
}

Explanation: This example involves multiple immutable references.

Example 13

fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    let r3 = &mut s;
    println!("{}, {}, and {}", r1, r2, r3);
}

Explanation: This example checks for a mutable reference after immutable ones.

Example 14

fn main() {
    let s1 = String::from("hello");
    let s2 = &s1;
    println!("s1: {}", s1);
    modify(s2);
}

fn modify(s: &String) {
    s.push_str(", world");
}

Explanation: This example tests attempting to modify a borrowed value in a function.

Example 15

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

Explanation: This example demonstrates the use of a variable after its value has been moved.

For each example, determine if it will compile and explain the reason based on your understanding of Rust's ownership and borrowing rules.

@xpepper
Copy link
Author

xpepper commented Apr 19, 2024

Produced using perplexity.ai and the following prompt:

I'm trying to learn ownership and borrowing in Rust programming language, and I would like you to help me practicing in recognizing code that violates Rust rules on ownership and borrowing, by showing me some code examples and then let me choose, for each example, if it would compile or not (and why it should not compile).

I'm going to give you same examples, please use them to have an idea of what kind of code example you could show me, but don't just copy those examples, try to come out with your own examples.

For example you could show me a code example like this

1 let s1 = String::from("hello");
2 let s2 = s1;
3 
4 println!("{}, world!", s1);

And I would have to recognize that this code does not compile because at line 4 s1 would be an invalid reference, since ownership moved to s2.

Another example you could show me would be something like this

fn main() {
    let s = String::from("hello");  

    takes_ownership(s);             
                                    
    let x = 5;                      

    makes_copy(x);                  

} 
  

fn takes_ownership(some_string: String) { 
    println!("{}", some_string);
} 
  

fn makes_copy(some_integer: i32) { 
    println!("{}", some_integer);
} 

Or this, for help me understand borrowing

fn main() {
    let s = String::from("hello");

    change(&s);
}

fn change(some_string: &String) {
    some_string.push_str(", world");
}

Or this one

let mut s = String::from("hello");

let r1 = &mut s;
let r2 = &mut s;

println!("{}, {}", r1, r2);

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