Bird
Raised Fist0
Rustprogramming~20 mins

Function ownership interaction in Rust - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Rust Ownership Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output of this Rust code involving ownership and borrowing?
Consider the following Rust code. What will it print when run?
Rust
fn main() {
    let s = String::from("hello");
    let len = calculate_length(&s);
    println!("The length of '{}' is {}.", s, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}
AThe length of 'hello' is 5.
BThe length of 'hello' is 0.
CCompile error due to ownership move.
DRuntime error due to use after move.
Attempts:
2 left
💡 Hint
Look at how the string is passed to the function: is it moved or borrowed?
❓ Predict Output
intermediate
2:00remaining
What happens when ownership is moved into a function?
What will be the output or error of this Rust code?
Rust
fn main() {
    let s = String::from("world");
    takes_ownership(s);
    println!("After function call: {}", s);
}

fn takes_ownership(some_string: String) {
    println!("Inside function: {}", some_string);
}
ACompile error: missing semicolon
B
Inside function: world
After function call: world
CRuntime error: use after free
D
Inside function: world
Compile error: borrow of moved value 's'
Attempts:
2 left
💡 Hint
Check what happens to ownership when passing s to takes_ownership.
🔧 Debug
advanced
2:00remaining
Identify the error in this Rust code with mutable references
This code tries to modify a string through a mutable reference. What error will the compiler report?
Rust
fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &mut s;
    r1.push_str(", world");
    r2.push_str("!");
    println!("{}", s);
}
ACompile error: cannot borrow 's' as immutable because it is also borrowed as mutable
BOutput: hello, world!
CCompile error: cannot borrow 's' as mutable more than once at a time
DRuntime error: data race detected
Attempts:
2 left
💡 Hint
Rust allows only one mutable reference at a time.
❓ Predict Output
advanced
2:00remaining
What is the output of this Rust code with ownership transfer and return?
What will this Rust program print?
Rust
fn main() {
    let s1 = String::from("hello");
    let s2 = takes_and_gives_back(s1);
    println!("s2 is: {}", s2);
}

fn takes_and_gives_back(a_string: String) -> String {
    a_string + " world"
}
As2 is: hello
Bs2 is: hello world
CCompile error: cannot move out of 'a_string' because it is borrowed
DRuntime error: use after move
Attempts:
2 left
💡 Hint
The function takes ownership and returns a new String.
❓ Predict Output
expert
3:00remaining
What is the output of this Rust code demonstrating ownership and borrowing with slices?
Analyze the code and select the correct output.
Rust
fn main() {
    let s = String::from("hello world");
    let word = first_word(&s);
    println!("First word: {}", word);
}

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}
AFirst word: hello
BFirst word: hello world
CCompile error: cannot return reference to local variable
DRuntime error: index out of bounds
Attempts:
2 left
💡 Hint
The function returns a slice up to the first space character.

Practice

(1/5)
1. What happens when a function in Rust takes ownership of a variable passed to it?
easy
A. The function borrows the variable temporarily.
B. The original variable can no longer be used after the function call.
C. The variable is copied and both original and function have ownership.
D. The variable is automatically cloned inside the function.

Solution

  1. Step 1: Understand ownership transfer

    When a function takes ownership, the original variable's ownership moves to the function.
  2. Step 2: Effect on original variable

    After the function call, the original variable is no longer valid and cannot be used.
  3. Final Answer:

    The original variable can no longer be used after the function call. -> Option B
  4. Quick Check:

    Ownership moves = original invalid [OK]
Hint: Ownership moves to function, original variable becomes unusable [OK]
Common Mistakes:
  • Thinking ownership is copied, not moved
  • Confusing borrowing with ownership transfer
  • Assuming automatic cloning happens
2. Which of the following function signatures correctly borrows a string slice without taking ownership?
easy
A. fn print_name(name: &str) { println!("{}", name); }
B. fn print_name(name: &String) { println!("{}", name); }
C. fn print_name(name: String) { println!("{}", name); }
D. fn print_name(name: String) -> String { name }

Solution

  1. Step 1: Identify borrowing syntax

    Borrowing a string slice uses &str type, which is a reference to string data.
  2. Step 2: Match function signature

    fn print_name(name: &str) { println!("{}", name); } uses &str, correctly borrowing without taking ownership.
  3. Final Answer:

    fn print_name(name: &str) { println!("{}", name); } -> Option A
  4. Quick Check:

    Borrow string slice = &str [OK]
Hint: Use &str to borrow string slices, not String type [OK]
Common Mistakes:
  • Using String type takes ownership
  • Using &String borrows but is less flexible than &str
  • Returning String does not borrow
3. What is the output of the following Rust code?
fn take_ownership(s: String) {
    println!("Inside: {}", s);
}

fn main() {
    let s = String::from("hello");
    take_ownership(s);
    println!("Outside: {}", s);
}
medium
A. Inside: hello Outside: hello
B. Inside: hello Outside:
C. Inside: hello Compile error: use of moved value 's'
D. Runtime error: use after free

Solution

  1. Step 1: Analyze ownership transfer in function call

    The function take_ownership takes ownership of s, moving it inside the function.
  2. Step 2: Check usage after ownership moved

    After the function call, s is no longer valid in main, so using it causes a compile error.
  3. Final Answer:

    Inside: hello Compile error: use of moved value 's' -> Option C
  4. Quick Check:

    Ownership moved = compile error on use after move [OK]
Hint: Using moved variable after function call causes compile error [OK]
Common Mistakes:
  • Assuming variable is still valid after move
  • Expecting runtime error instead of compile error
  • Thinking variable is copied automatically
4. Identify the error in this Rust code and choose the fix:
fn add_one(num: &i32) -> i32 {
    *num + 1
}

fn main() {
    let x = 5;
    let y = add_one(x);
    println!("{}", y);
}
medium
A. No error, code runs correctly.
B. Change function parameter to num: i32 to take ownership.
C. Change return type to &i32 to return a reference.
D. Change call to add_one(&x) to pass a reference.

Solution

  1. Step 1: Check function parameter type

    Function expects a reference &i32, but main passes x (i32) directly.
  2. Step 2: Fix function call

    Pass a reference &x to match parameter type and avoid type mismatch error.
  3. Final Answer:

    Change call to add_one(&x) to pass a reference. -> Option D
  4. Quick Check:

    Pass reference when function expects &i32 [OK]
Hint: Match argument type with parameter type exactly [OK]
Common Mistakes:
  • Passing value instead of reference
  • Changing return type unnecessarily
  • Ignoring compiler type mismatch errors
5. Given this Rust code, what is the correct way to write a function that takes ownership of a vector, adds an element, and returns ownership back?
fn add_element(vec: Vec<i32>) -> Vec<i32> {
    // Add 10 to the vector
    vec.push(10);
    vec
}
hard
A. fn add_element(mut vec: Vec<i32>) -> Vec<i32> { vec.push(10); vec }
B. fn add_element(vec: &Vec<i32>) -> Vec<i32> { vec.push(10); vec.clone() }
C. fn add_element(vec: Vec<i32>) { vec.push(10); }
D. fn add_element(vec: &mut Vec<i32>) { vec.push(10); }

Solution

  1. Step 1: Understand ownership and mutability

    To modify the vector, the function must take ownership and have mutable access, so parameter must be mutable.
  2. Step 2: Return ownership after modification

    Return the modified vector to give ownership back to the caller.
  3. Final Answer:

    fn add_element(mut vec: Vec<i32>) -> Vec<i32> { vec.push(10); vec } -> Option A
  4. Quick Check:

    Mutable ownership + return ownership = fn add_element(mut vec: Vec<i32>) -> Vec<i32> { vec.push(10); vec } [OK]
Hint: Use mut parameter and return vector to keep ownership [OK]
Common Mistakes:
  • Forgetting mut keyword for parameter
  • Trying to modify borrowed vector without mut
  • Not returning the vector after modification
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard