16. What does this println! with a shadowed variable print?
let x = 5;
let x = x + 2;
let x = x * 2;
println!("{}", x);
Output:
14
Each let x creates a new binding that shadows the previous. 5 → 5+2 = 7 → 7*2 = 14. Shadowing lets you rebind names without mut. Note let x = x + 2 reads the old x on the right before shadowing.
17. What does this println! with a Vec print?
let mut v = vec![1, 2, 3];
v.push(4);
println!("{:?}", v);
println!("{}", v.len());
println!("{}", v[1]);
Output:
[1, 2, 3, 4]
4
2
push appends → [1, 2, 3, 4]. len is 4. v[1] is 2. {:?} prints a Vec with brackets and commas.
18. What does this println! with indexing print?
let v = vec![10, 20, 30];
let first = v.get(0);
let missing = v.get(5);
println!("{:?}", first);
println!("{:?}", missing);
Output:
Some(10)
None
v.get(0) returns Some(&10); printing with {:?} shows Some(10) (the reference’s Debug shows the pointee). v.get(5) is out of bounds and returns None instead of panicking. Indexing with v[5] would panic — get is the safe alternative.
19. What does this println! with match on Option print?
let opt = Some(42);
match opt {
Some(n) => println!("value: {}", n),
None => println!("no value"),
}
let none: Option<i32> = None;
match none {
Some(n) => println!("value: {}", n),
None => println!("no value"),
}
Output:
value: 42
no value
Some(42) matches the Some(n) arm, binding n to 42. None matches the None arm. match on Option is exhaustive — both arms must be handled.
20. What does this println! with string slicing print?
let s = "hello world";
println!("{}", &s[0..5]);
println!("{}", &s[6..]);
println!("{}", s.len());
Output:
hello
world
11
&s[0..5] takes bytes 0-4 → "hello". &s[6..] takes from byte 6 to end → "world". s.len() is 11 bytes. String slicing must land on character boundaries — slicing mid-UTF-8-char panics.
21. What does this println! with str vs String print?
let s1: &str = "hello";
let s2: String = String::from("hello");
println!("{}", s1);
println!("{}", s2);
println!("{}", s1 == s2);
Output:
hello
hello
true
&str and String print identically via Display. == works because String implements PartialEq<&str> (and there’s a PartialEq<String> for &str) — comparing contents, not identity → true.
22. What does this println! with move semantics print?
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s2);
// println!("{}", s1); // compile error: borrow of moved value
Output:
hello
let s2 = s1 moves s1’s ownership to s2. The commented line would be a compile error — using s1 after the move is illegal. Rust moves values by default for non-Copy types like String, preventing use-after-move at compile time.
23. What does this println! with a clone print?
let s1 = String::from("hello");
let s2 = s1.clone();
println!("{}", s1);
println!("{}", s2);
Output:
hello
hello
.clone() deep-copies the heap data, so both s1 and s2 are valid and own separate strings. Without the clone, s2 = s1 would move and s1 couldn’t be used. Cloning is explicit in Rust — no hidden copies.
24. What does this println! with borrowing print?
let v = vec![1, 2, 3];
let first = &v[0];
println!("{}", first);
println!("{}", *first);
println!("{}", v.len());
Output:
1
1
3
&v[0] borrows the first element. Printing first with {} dereferences implicitly (automatically), so both println!("{}", first) and println!("{}", *first) output 1. v is still usable because the borrow is alive but read-only.
25. What does this println! with a reference print?
let x = 5;
let y = &x;
println!("{}, {}", x, *y);
let mut z = 6;
let zr = &mut z;
*zr = 10;
println!("{}", z);
Output:
5, 5
10
y borrows x; *y dereferences to 5. zr is a mutable borrow; *zr = 10 writes through it, updating z to 10. References don’t copy the value — they point at it.
26. What does this println! with a tuple print?
let t = (10, "rust", true);
println!("{:?}", t);
println!("{}", t.0);
let (a, _, c) = t;
println!("{} {}", a, c);
Output:
(10, "rust", true)
10
10 true
{:?} shows the tuple’s debug form. t.0 is 10. Destructuring let (a, _, c) = t binds a=10 (skip with _) and c=true. Tuples support both field-by-number access and pattern destructuring.
27. What does this println! with a loop print?
let mut i = 0;
let result = loop {
i += 1;
if i >= 3 {
break i * 10;
}
};
println!("{}", result);
Output:
30
loop runs until break, which can yield a value. i becomes 1, then 2, then 3, and 3 >= 3 triggers break 3 * 10 = 30. result is 30. loop { } is Rust’s number-free infinite loop that can return a value.
28. What does this println! with if as expression print?
let n = 7;
let parity = if n % 2 == 0 { "even" } else { "odd" };
println!("{}", parity);
let larger = if n > 5 { 10 } else { -10 };
println!("{}", larger);
Output:
odd
10
if is an expression in Rust — the chosen arm becomes the value without a borrow issue. 7 is odd → "odd". 7 > 5 → 10. Both arms must be the same type.
29. What does this println! with ? on Option print?
fn parse(s: &str) -> Option<i32> {
s.parse().ok()
}
match parse("42") {
Some(n) => println!("parsed: {}", n),
None => println!("failed"),
}
match parse("abc") {
Some(n) => println!("parsed: {}", n),
None => println!("failed"),
}
"42".parse::<i32>() succeeds → Some(42). "abc" fails to parse → Err, and .ok() converts it to None.
Output:
parsed: 42
failed
30. What does this println! with enum print?
enum Status {
Active,
Inactive(u32),
}
let s1 = Status::Active;
let s2 = Status::Inactive(7);
match s1 {
Status::Active => println!("active"),
Status::Inactive(n) => println!("inactive: {}", n),
}
match s2 {
Status::Active => println!("active"),
Status::Inactive(n) => println!("inactive: {}", n),
}
Output:
active
inactive: 7
Status::Active matches the first arm. Status::Inactive(7) binds n = 7 in the second arm. Enums can carry data, and match is exhaustive — the compiler forces all variants to be handled.
Premium Content
Unlock Output Questions - Part 2 and all premium lessons with a subscription.
From ₹199.99/year — See plans