It checks if a function returned an error. If there is an error, it returns it immediately from the current function. Otherwise, it continues with the successful value.
Click to reveal answer
beginner
How does ? help with error propagation?
It lets you write less code by automatically returning errors up the call stack without needing explicit match or if let statements.
Click to reveal answer
intermediate
Can ? be used in functions that do not return a Result or Option?
No. The function must return a compatible type like Result or Option for ? to work.
Click to reveal answer
beginner
Example: What does this code do?<br><pre>let file = std::fs::File::open("foo.txt")?;</pre>
It tries to open the file "foo.txt". If it fails, the error is returned from the current function immediately. If it succeeds, the file handle is stored in file.
Click to reveal answer
intermediate
Why is using ? considered more readable than manual error handling?
Because it reduces nested code and boilerplate, making the main logic clearer and easier to follow.
Click to reveal answer
What happens when ? encounters an error in a Result?
AIt returns the error from the current function immediately.
BIt ignores the error and continues.
CIt panics and stops the program.
DIt converts the error to a string.
✗ Incorrect
The ? operator returns the error immediately from the current function, propagating it up.
Which return types are compatible with using ??
AOnly <code>Result</code> and <code>Option</code>.
BAny type.
COnly <code>String</code>.
DOnly <code>bool</code>.
✗ Incorrect
? works with Result and Option types to propagate errors or None values.
What is the main benefit of using ? in Rust?
AConverts errors to warnings.
BMakes the program run faster.
CAutomatically fixes errors.
DSimplifies error handling by reducing boilerplate.
✗ Incorrect
? reduces the need for explicit error checks, making code cleaner and easier to read.
Can you use ? inside a function that returns void (unit type)?
AOnly if you import a special crate.
BYes, always.
CNo, the function must return <code>Result</code> or <code>Option</code>.
DOnly in async functions.
✗ Incorrect
? requires the function to return a compatible type like Result or Option.
What does this code do?
let content = std::fs::read_to_string("file.txt")?;
APrints the file content to the screen.
BReads the file content or returns an error immediately.
CIgnores any errors and returns empty string.
DCreates a new file named "file.txt".
✗ Incorrect
It tries to read the file content. If it fails, the error is returned immediately using ?.
Explain how the ? operator helps with error propagation in Rust.
Think about how errors move up the call stack without extra code.
You got /4 concepts.
Describe a simple example where using ? makes your Rust code easier to read.
Imagine you want to open a file and return an error if it fails.
You got /4 concepts.
Practice
(1/5)
1. What does the ? operator do in Rust when used with a Result type?
easy
A. It ignores any error and always returns the success value.
B. It converts the Result into an Option.
C. It returns the error immediately if there is one, otherwise unwraps the value.
D. It retries the operation until it succeeds.
Solution
Step 1: Understand the ? operator behavior
The ? operator checks if the Result is an Err. If yes, it returns the error from the current function immediately.
Step 2: What happens if Result is Ok?
If the Result is Ok, it unwraps the value inside and continues execution.
Final Answer:
It returns the error immediately if there is one, otherwise unwraps the value. -> Option C
Quick Check:
? returns error or unwraps value [OK]
Hint: Remember: ? returns error early or unwraps success [OK]
Common Mistakes:
Thinking ? converts Result to Option
Assuming ? ignores errors
Believing ? retries operations
2. Which of the following function signatures correctly allows using the ? operator inside the function to propagate std::io::Error?
easy
A. fn read_file() -> String
B. fn read_file() -> Result
C. fn read_file() -> ()
D. fn read_file() -> Option<String>
Solution
Step 1: Identify return types compatible with ?
The ? operator works only in functions returning Result or Option.
Step 2: Check each signature
fn read_file() -> String returns String directly, no error type, so ? can't be used. fn read_file() -> Result returns Result, which supports ?. fn read_file() -> () returns unit (), no error handling. fn read_file() -> Option<String> returns Option, which supports ? for absence but cannot propagate std::io::Error.
Final Answer:
fn read_file() -> Result -> Option B
Quick Check:
Function must return Result or Option for ? [OK]
Hint: Use Result or Option return type to use ? [OK]
Common Mistakes:
Using ? in functions returning plain types
Forgetting to specify error type in Result
Confusing Option and Result return types
3. What is the output of the following Rust code?
fn parse_number(s: &str) -> Result {
let num = s.parse::<i32>()?;
Ok(num * 2)
}
fn main() {
match parse_number("10") {
Ok(n) => println!("{}", n),
Err(e) => println!("Error: {}", e),
}
}
medium
A. 20
B. Error: invalid digit found in string
C. 10
D. Compilation error
Solution
Step 1: Understand parse_number function
The function tries to parse the string "10" to an integer using s.parse::<i32>()?. Since "10" is valid, it unwraps to 10.
Step 2: Calculate the returned value
It multiplies the parsed number by 2, so 10 * 2 = 20, then returns Ok(20).
Step 3: Check main output
The match prints the number 20 because parsing succeeded.
Final Answer:
20 -> Option A
Quick Check:
Valid parse returns doubled number [OK]
Hint: Valid parse with ? returns doubled value [OK]
Common Mistakes:
Assuming parse fails and prints error
Confusing output with input string
Thinking code won't compile due to ?
4. Identify the error in this Rust function using ? and fix it:
fn get_first_char(s: &str) -> Result {
let first = s.chars().next()?;
Ok(first)
}
medium
A. Change next() to next().ok_or("Empty string".to_string())?
B. Change return type to Option<char>
C. Replace ? with .unwrap()
D. No error, code is correct
Solution
Step 1: Analyze next() return type
next() returns an Option<char>, but ? requires Result or Option compatible with function return.
Step 2: Fix error propagation
Since function returns Result, convert Option to Result using next().ok_or("Empty string".to_string())? to propagate error properly.
Final Answer:
Change next() to next().ok_or("Empty string".to_string())? -> Option A
Quick Check:
Convert Option to Result for ? in Result function [OK]
Hint: Convert Option to Result with ok_or before ? [OK]
Common Mistakes:
Using ? directly on Option in Result function
Ignoring error conversion from Option to Result
Replacing ? with .unwrap() causing panic
5. You want to write a function that reads a file and returns the number of lines. It should propagate any IO errors using ?. Which of the following implementations correctly uses ? to propagate errors?
hard
A. fn count_lines(path: &str) -> Option<usize> {
let content = std::fs::read_to_string(path)?;
Some(content.lines().count())
}
B. fn count_lines(path: &str) -> usize {
let content = std::fs::read_to_string(path)?;
content.lines().count()
}
C. fn count_lines(path: &str) -> Result {
let content = std::fs::read_to_string(path).unwrap();
Ok(content.lines().count())
}
D. fn count_lines(path: &str) -> Result {
let content = std::fs::read_to_string(path)?;
Ok(content.lines().count())
}
Solution
Step 1: Check function return type compatibility
The function returns Result, so it can use ? to propagate IO errors.
Step 2: Analyze each option
fn count_lines(path: &str) -> Result {
let content = std::fs::read_to_string(path)?;
Ok(content.lines().count())
} uses ? correctly and returns Ok with line count. fn count_lines(path: &str) -> usize {
let content = std::fs::read_to_string(path)?;
content.lines().count()
} returns usize directly but uses ? which is invalid here. fn count_lines(path: &str) -> Result {
let content = std::fs::read_to_string(path).unwrap();
Ok(content.lines().count())
} uses unwrap() which panics on error, not propagates. fn count_lines(path: &str) -> Option<usize> {
let content = std::fs::read_to_string(path)?;
Some(content.lines().count())
} returns Option but read_to_string returns Result, so ? cannot be used directly.
Final Answer:
fn count_lines(path: &str) -> Result<usize, std::io::Error> {
let content = std::fs::read_to_string(path)?;
Ok(content.lines().count())
} -> Option D
Quick Check:
Return Result and use ? to propagate errors [OK]
Hint: Match function return type with ? usage for error propagation [OK]
Common Mistakes:
Using ? in functions without Result or Option return
Using unwrap() instead of propagating errors
Mismatching return types and error handling
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.