Blocks are code sections enclosed in curly braces {} that define a scope, while scopes determine where variables are accessible and when they are dropped. When a variable's owner goes out of scope at the end of a block, the variable is dropped and its memory is freed.
fn main() {
let x = 5; // x is valid from here
{
let y = 10; // y is valid only inside this block
println!("y is {y}");
} // y goes out of scope and is dropped here
println!("x is {x}"); // x is still valid
// println!("y is {y}"); // Error: y is out of scope
}