Compare commits

...

7 commits

Author SHA1 Message Date
Enrico
b2f62bdad5
Merge e59c65cf45 into 0432e07864 2024-10-14 11:09:52 -07:00
Mo
0432e07864
Merge pull request #2130 from Nahor/typo
Some checks failed
Rustlings Tests / clippy (push) Has been cancelled
Rustlings Tests / fmt (push) Has been cancelled
Rustlings Tests / test (macOS-latest) (push) Has been cancelled
Rustlings Tests / test (ubuntu-latest) (push) Has been cancelled
Rustlings Tests / test (windows-latest) (push) Has been cancelled
Rustlings Tests / dev-check (push) Has been cancelled
Web / Build and deploy site and docs (push) Has been cancelled
Fix typos
2024-10-14 20:06:30 +02:00
Nahor
f33ba139b4 Fix typos 2024-10-14 10:17:17 -07:00
mo8it
990a722852 Limit the maximum number of exercises to 999 2024-10-14 15:57:44 +02:00
mo8it
a675cb5754 Replace ahash with foldhash 2024-10-14 15:24:42 +02:00
Enrico
e59c65cf45 chore: Refactored to adhere to new rustlings version 2024-09-29 20:58:33 +02:00
Enrico
1c27aeead9 feat: add functions6.rs and move_semantics6.rs exercises about closures 2024-09-28 11:59:09 +02:00
15 changed files with 146 additions and 76 deletions

86
Cargo.lock generated
View file

@ -2,18 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.15" version = "0.6.15"
@ -71,9 +59,9 @@ checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
@ -95,9 +83,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.18" version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -105,9 +93,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.18" version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -198,6 +186,12 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "foldhash"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
[[package]] [[package]]
name = "fsevent-sys" name = "fsevent-sys"
version = "4.1.0" version = "4.1.0"
@ -209,9 +203,9 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.5" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]] [[package]]
name = "heck" name = "heck"
@ -227,9 +221,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.5.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@ -377,9 +371,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]] [[package]]
name = "os_pipe" name = "os_pipe"
@ -416,9 +410,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.86" version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -434,9 +428,9 @@ dependencies = [
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.6" version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
] ]
@ -458,10 +452,10 @@ dependencies = [
name = "rustlings" name = "rustlings"
version = "6.3.0" version = "6.3.0"
dependencies = [ dependencies = [
"ahash",
"anyhow", "anyhow",
"clap", "clap",
"crossterm", "crossterm",
"foldhash",
"notify", "notify",
"os_pipe", "os_pipe",
"rustix", "rustix",
@ -587,9 +581,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.77" version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -598,9 +592,9 @@ dependencies = [
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.12.0" version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"fastrand", "fastrand",
@ -643,12 +637,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.5.0" version = "2.5.0"
@ -852,23 +840,3 @@ checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -46,10 +46,10 @@ include = [
] ]
[dependencies] [dependencies]
ahash = { version = "0.8.11", default-features = false }
anyhow = "1.0.89" anyhow = "1.0.89"
clap = { version = "4.5.18", features = ["derive"] } clap = { version = "4.5.20", features = ["derive"] }
crossterm = { version = "0.28.1", default-features = false, features = ["windows", "events"] } crossterm = { version = "0.28.1", default-features = false, features = ["windows", "events"] }
foldhash = "0.1.3"
notify = { version = "6.1.1", default-features = false, features = ["macos_fsevent"] } notify = { version = "6.1.1", default-features = false, features = ["macos_fsevent"] }
os_pipe = "1.2.1" os_pipe = "1.2.1"
rustlings-macros = { path = "rustlings-macros", version = "=6.3.0" } rustlings-macros = { path = "rustlings-macros", version = "=6.3.0" }
@ -61,7 +61,7 @@ toml_edit.workspace = true
rustix = { version = "0.38.37", default-features = false, features = ["std", "stdio", "termios"] } rustix = { version = "0.38.37", default-features = false, features = ["std", "stdio", "termios"] }
[dev-dependencies] [dev-dependencies]
tempfile = "3.12.0" tempfile = "3.13.0"
[profile.release] [profile.release]
panic = "abort" panic = "abort"

View file

@ -5,7 +5,7 @@ disallowed-types = [
] ]
disallowed-methods = [ disallowed-methods = [
# We use `ahash` instead of the default hasher. # We use `foldhash` instead of the default hasher.
"std::collections::HashSet::new", "std::collections::HashSet::new",
"std::collections::HashSet::with_capacity", "std::collections::HashSet::with_capacity",
# Inefficient. Use `.queue(…)` instead. # Inefficient. Use `.queue(…)` instead.

View file

@ -26,6 +26,8 @@ bin = [
{ name = "functions4_sol", path = "../solutions/02_functions/functions4.rs" }, { name = "functions4_sol", path = "../solutions/02_functions/functions4.rs" },
{ name = "functions5", path = "../exercises/02_functions/functions5.rs" }, { name = "functions5", path = "../exercises/02_functions/functions5.rs" },
{ name = "functions5_sol", path = "../solutions/02_functions/functions5.rs" }, { name = "functions5_sol", path = "../solutions/02_functions/functions5.rs" },
{ name = "functions6", path = "../exercises/02_functions/functions6.rs" },
{ name = "functions6_sol", path = "../solutions/02_functions/functions6.rs" },
{ name = "if1", path = "../exercises/03_if/if1.rs" }, { name = "if1", path = "../exercises/03_if/if1.rs" },
{ name = "if1_sol", path = "../solutions/03_if/if1.rs" }, { name = "if1_sol", path = "../solutions/03_if/if1.rs" },
{ name = "if2", path = "../exercises/03_if/if2.rs" }, { name = "if2", path = "../exercises/03_if/if2.rs" },
@ -60,6 +62,8 @@ bin = [
{ name = "move_semantics4_sol", path = "../solutions/06_move_semantics/move_semantics4.rs" }, { name = "move_semantics4_sol", path = "../solutions/06_move_semantics/move_semantics4.rs" },
{ name = "move_semantics5", path = "../exercises/06_move_semantics/move_semantics5.rs" }, { name = "move_semantics5", path = "../exercises/06_move_semantics/move_semantics5.rs" },
{ name = "move_semantics5_sol", path = "../solutions/06_move_semantics/move_semantics5.rs" }, { name = "move_semantics5_sol", path = "../solutions/06_move_semantics/move_semantics5.rs" },
{ name = "move_semantics6", path = "../exercises/06_move_semantics/move_semantics6.rs" },
{ name = "move_semantics6_sol", path = "../solutions/06_move_semantics/move_semantics6.rs" },
{ name = "structs1", path = "../exercises/07_structs/structs1.rs" }, { name = "structs1", path = "../exercises/07_structs/structs1.rs" },
{ name = "structs1_sol", path = "../solutions/07_structs/structs1.rs" }, { name = "structs1_sol", path = "../solutions/07_structs/structs1.rs" },
{ name = "structs2", path = "../exercises/07_structs/structs2.rs" }, { name = "structs2", path = "../exercises/07_structs/structs2.rs" },

View file

@ -1,8 +1,9 @@
# Functions # Functions
Here, you'll learn how to write functions and how the Rust compiler can help you debug errors even Here, you'll learn how to write functions and how the Rust compiler can help you debug errors even
in more complex code. in more complex code. You will also learn what is the difference with closures.
## Further information ## Further information
- [How Functions Work](https://doc.rust-lang.org/book/ch03-03-how-functions-work.html) - [How Functions Work](https://doc.rust-lang.org/book/ch03-03-how-functions-work.html)
- [Closures](https://doc.rust-lang.org/book/ch13-01-closures.html)

View file

@ -0,0 +1,19 @@
// functions6.rs
//
// Here you can practice special functions called `closures`, that can capture
// variables of their parent context.
// Fix the code below to make it compile, without changing the two closure
// definitions.
//
// Execute `rustlings hint functions6` or use the `hint` watch subcommand for
// some hints.
fn main() {
// TODO: ensure the definition of captured variable
let closure_1 = |input_var: u32| -> u32 {input_var + outer_var};
println!("Closure#1 returns {}", closure_1(5));
let closure_2 = |input_var| println!("Closure#2 (input_var {})", input_var);
closure_2(2);
closure_2("5"); // TODO: look at the captured variable type here
}

View file

@ -0,0 +1,25 @@
// move_semantics6.rs
//
// Here you will practice how mutable/immutable borrowing works in the context
// of a closure.
//
// Try to fix this code to make it compile and not panic.
// You can't change anything except removing 1 line.
//
// Execute `rustlings hint move_semantics7` or use the `hint` watch subcommand
// for a hint.
fn main() {
let mut counter = 0;
let mut increment = || {
counter += 1;
println!("counter equals {}", counter);
};
increment();
let _reborrowed_counter = &counter; // TODO: figure out where to put this borrowing instruction
increment();
assert_eq!(counter, 2);
}

View file

@ -3,7 +3,7 @@
| Exercise | Book Chapter | | Exercise | Book Chapter |
| ---------------------- | ------------------- | | ---------------------- | ------------------- |
| variables | §3.1 | | variables | §3.1 |
| functions | §3.3 | | functions | §3.3, §13.1 |
| if | §3.5 | | if | §3.5 |
| primitive_types | §3.2, §4.3 | | primitive_types | §3.2, §4.3 |
| vecs | §8.1 | | vecs | §8.1 |

View file

@ -187,6 +187,20 @@ There are two solutions:
1. Add the `return` keyword before `num * num;` 1. Add the `return` keyword before `num * num;`
2. Remove the semicolon `;` after `num * num`""" 2. Remove the semicolon `;` after `num * num`"""
[[exercises]]
name = "functions6"
dir = "02_functions"
test = false
hint = """
Hint FIX #1: Closures can capture variables defined in the outer context.
Hint FIX #2: Closures can infer both input and returned types, when they are not
specified in the signature. But the closure cannot be reused with different
input types.
Read more about closures in the rust book dedicated section:
https://doc.rust-lang.org/book/ch13-01-closures.html"""
# IF # IF
[[exercises]] [[exercises]]
@ -391,6 +405,18 @@ The first problem is that `get_char` is taking ownership of the string. So
Once you've fixed that, `string_uppercase`'s function signature will also need Once you've fixed that, `string_uppercase`'s function signature will also need
to be adjusted.""" to be adjusted."""
[[exercises]]
name = "move_semantics6"
dir = "06_move_semantics"
test = false
hint = """
When a closure captures a variable to modify it, it actually borrows that variable
as a mutable reference. In this exercise, the closure mutably borrows the `counter`
variable, thus, any attempt to borrow `counter` between closure calls leads to an error.
You cannot immutably borrow a variable if a mutable closure is
called later in the scope."""
# STRUCTS # STRUCTS
[[exercises]] [[exercises]]

View file

@ -0,0 +1,9 @@
fn main() {
let outer_var = 1;
let closure_1 = |input_var: u32| -> u32 { input_var + outer_var };
println!("Closure#1 returns {}", closure_1(5));
let closure_2 = |input_var| println!("Closure#2 (input_var {})", input_var);
closure_2(2);
closure_2(5);
}

View file

@ -0,0 +1,14 @@
fn main() {
let mut counter = 0;
let mut increment = || {
counter += 1;
println!("counter equals {}", counter);
};
increment();
increment();
let _reborrowed_counter = &counter;
assert_eq!(counter, 2);
}

View file

@ -148,11 +148,11 @@ impl AppState {
let mut done_exercises = hash_set_with_capacity(exercises.len()); let mut done_exercises = hash_set_with_capacity(exercises.len());
for done_exerise_name in lines { for done_exercise_name in lines {
if done_exerise_name.is_empty() { if done_exercise_name.is_empty() {
break; break;
} }
done_exercises.insert(done_exerise_name); done_exercises.insert(done_exercise_name);
} }
for (ind, exercise) in exercises.iter_mut().enumerate() { for (ind, exercise) in exercises.iter_mut().enumerate() {

View file

@ -1,10 +1,9 @@
use ahash::AHasher; use foldhash::fast::FixedState;
use std::hash::BuildHasherDefault;
/// DOS attacks aren't a concern for Rustlings. Therefore, we use `ahash` with fixed seeds. /// DOS attacks aren't a concern for Rustlings. Therefore, we use `foldhash` with a fixed state.
pub type HashSet<T> = std::collections::HashSet<T, BuildHasherDefault<AHasher>>; pub type HashSet<T> = std::collections::HashSet<T, FixedState>;
#[inline] #[inline]
pub fn hash_set_with_capacity<T>(capacity: usize) -> HashSet<T> { pub fn hash_set_with_capacity<T>(capacity: usize) -> HashSet<T> {
HashSet::with_capacity_and_hasher(capacity, BuildHasherDefault::<AHasher>::default()) HashSet::with_capacity_and_hasher(capacity, FixedState::default())
} }

View file

@ -17,6 +17,7 @@ use crate::{
CURRENT_FORMAT_VERSION, CURRENT_FORMAT_VERSION,
}; };
const MAX_N_EXERCISES: usize = 999;
const MAX_EXERCISE_NAME_LEN: usize = 32; const MAX_EXERCISE_NAME_LEN: usize = 32;
// Find a char that isn't allowed in the exercise's `name` or `dir`. // Find a char that isn't allowed in the exercise's `name` or `dir`.
@ -201,7 +202,7 @@ fn check_exercises_unsolved(
for (exercise_name, handle) in handles { for (exercise_name, handle) in handles {
let Ok(result) = handle.join() else { let Ok(result) = handle.join() else {
bail!("Panic while trying to run the exericse {exercise_name}"); bail!("Panic while trying to run the exercise {exercise_name}");
}; };
match result { match result {
@ -299,7 +300,7 @@ fn check_solutions(
for (exercise_info, handle) in info_file.exercises.iter().zip(handles) { for (exercise_info, handle) in info_file.exercises.iter().zip(handles) {
let Ok(check_result) = handle.join() else { let Ok(check_result) = handle.join() else {
bail!( bail!(
"Panic while trying to run the solution of the exericse {}", "Panic while trying to run the solution of the exercise {}",
exercise_info.name, exercise_info.name,
); );
}; };
@ -347,6 +348,10 @@ fn check_solutions(
pub fn check(require_solutions: bool) -> Result<()> { pub fn check(require_solutions: bool) -> Result<()> {
let info_file = InfoFile::parse()?; let info_file = InfoFile::parse()?;
if info_file.exercises.len() > MAX_N_EXERCISES {
bail!("The maximum number of exercises is {MAX_N_EXERCISES}");
}
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
// A hack to make `cargo run -- dev check` work when developing Rustlings. // A hack to make `cargo run -- dev check` work when developing Rustlings.
check_cargo_toml(&info_file.exercises, "dev/Cargo.toml", b"../")?; check_cargo_toml(&info_file.exercises, "dev/Cargo.toml", b"../")?;

View file

@ -166,7 +166,7 @@ pub fn progress_bar<'a>(
total: u16, total: u16,
term_width: u16, term_width: u16,
) -> io::Result<()> { ) -> io::Result<()> {
debug_assert!(total < 1000); debug_assert!(total <= 999);
debug_assert!(progress <= total); debug_assert!(progress <= total);
const PREFIX: &[u8] = b"Progress: ["; const PREFIX: &[u8] = b"Progress: [";