From a7a881809f462688b26ba7b81de85753c3507c22 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 12:53:44 +0200 Subject: [PATCH 01/29] Check is_terminal --- src/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index a9f7b4a1..3c96d1a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result}; use app_state::StateFileStatus; use clap::{Parser, Subcommand}; use std::{ - io::{self, BufRead, StdoutLock, Write}, + io::{self, BufRead, IsTerminal, StdoutLock, Write}, path::Path, process::exit, }; @@ -148,6 +148,10 @@ fn main() -> Result<()> { match args.command { None => { + if !io::stdout().is_terminal() { + bail!("Unsupported or missing terminal/TTY"); + } + let notify_exercise_names = if args.manual_run { None } else { From a4091ade5cde7602acef0601cb7f69984fcad009 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 14:40:35 +0200 Subject: [PATCH 02/29] iterators3: Add `IntegerOverflow` error variant --- exercises/18_iterators/iterators3.rs | 11 ++++++++++- solutions/18_iterators/iterators3.rs | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/exercises/18_iterators/iterators3.rs b/exercises/18_iterators/iterators3.rs index 65a05734..6b1eca17 100644 --- a/exercises/18_iterators/iterators3.rs +++ b/exercises/18_iterators/iterators3.rs @@ -1,12 +1,16 @@ #[derive(Debug, PartialEq, Eq)] enum DivisionError { + // Example: 42 / 0 DivideByZero, + // Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1` + IntegerOverflow, + // Example: 5 / 2 = 2.5 NotDivisible, } // TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`. // Otherwise, return a suitable error. -fn divide(a: i32, b: i32) -> Result { +fn divide(a: i64, b: i64) -> Result { todo!(); } @@ -42,6 +46,11 @@ mod tests { assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero)); } + #[test] + fn test_integer_overflow() { + assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow)); + } + #[test] fn test_not_divisible() { assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible)); diff --git a/solutions/18_iterators/iterators3.rs b/solutions/18_iterators/iterators3.rs index d66d1ef3..11aa1ec8 100644 --- a/solutions/18_iterators/iterators3.rs +++ b/solutions/18_iterators/iterators3.rs @@ -1,6 +1,10 @@ #[derive(Debug, PartialEq, Eq)] enum DivisionError { + // Example: 42 / 0 DivideByZero, + // Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1` + IntegerOverflow, + // Example: 5 / 2 = 2.5 NotDivisible, } @@ -9,6 +13,10 @@ fn divide(a: i64, b: i64) -> Result { return Err(DivisionError::DivideByZero); } + if a == i64::MIN && b == -1 { + return Err(DivisionError::IntegerOverflow); + } + if a % b != 0 { return Err(DivisionError::NotDivisible); } @@ -51,6 +59,11 @@ mod tests { assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero)); } + #[test] + fn test_integer_overflow() { + assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow)); + } + #[test] fn test_not_divisible() { assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible)); From 2d5d70693a879f07fcd941c21da3a3760cb81db6 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 15:05:58 +0200 Subject: [PATCH 03/29] errors3: Add a comment to prevent changing the wrong line --- exercises/13_error_handling/errors3.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/13_error_handling/errors3.rs b/exercises/13_error_handling/errors3.rs index 33a7b877..8e8c38a2 100644 --- a/exercises/13_error_handling/errors3.rs +++ b/exercises/13_error_handling/errors3.rs @@ -19,6 +19,7 @@ fn main() { let mut tokens = 100; let pretend_user_input = "8"; + // Don't change this line. let cost = total_cost(pretend_user_input)?; if cost > tokens { From bf698659b07bab2d6d4997e2637f1d304a293c5b Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 15:20:23 +0200 Subject: [PATCH 04/29] Sync comment from exercise --- solutions/quizzes/quiz2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/quizzes/quiz2.rs b/solutions/quizzes/quiz2.rs index 2f55f065..58cbe4e2 100644 --- a/solutions/quizzes/quiz2.rs +++ b/solutions/quizzes/quiz2.rs @@ -6,7 +6,7 @@ // - Append "bar" to the string a specified amount of times // // The exact form of this will be: -// - The input is going to be a vector of a 2-length tuple, +// - The input is going to be a vector of 2-length tuples, // the first element is the string, the second one is the command. // - The output element is going to be a vector of strings. From 08c408aae042509526e8cc1f175e7a010836f53d Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 15:20:56 +0200 Subject: [PATCH 05/29] Add hint about string concatination with + --- rustlings-macros/info.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index 715778dd..c9fc65aa 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -585,7 +585,7 @@ https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-value-based-on- [[exercises]] name = "quiz2" dir = "quizzes" -hint = "No hints this time ;)" +hint = "The `+` operator can concatinate a `String` with a `&str`." # OPTIONS @@ -748,7 +748,9 @@ name = "traits1" dir = "15_traits" hint = """ More about traits in The Book: -https://doc.rust-lang.org/book/ch10-02-traits.html""" +https://doc.rust-lang.org/book/ch10-02-traits.html + +The `+` operator can concatinate a `String` with a `&str`.""" [[exercises]] name = "traits2" From 69021e1497f62d52fd2b41d5e5b71ca46b76d7c0 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 16:00:12 +0200 Subject: [PATCH 06/29] Remove stable from book links --- exercises/04_primitive_types/README.md | 4 ++-- exercises/05_vecs/README.md | 2 +- exercises/12_options/README.md | 2 +- exercises/14_generics/README.md | 2 +- rustlings-macros/info.toml | 18 +++++++++--------- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/exercises/04_primitive_types/README.md b/exercises/04_primitive_types/README.md index cea69b02..d67668a3 100644 --- a/exercises/04_primitive_types/README.md +++ b/exercises/04_primitive_types/README.md @@ -5,5 +5,5 @@ compiler. In this section, we'll go through the most important ones. ## Further information -- [Data Types](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html) -- [The Slice Type](https://doc.rust-lang.org/stable/book/ch04-03-slices.html) +- [Data Types](https://doc.rust-lang.org/book/ch03-02-data-types.html) +- [The Slice Type](https://doc.rust-lang.org/book/ch04-03-slices.html) diff --git a/exercises/05_vecs/README.md b/exercises/05_vecs/README.md index 8ff9b85f..e1b61285 100644 --- a/exercises/05_vecs/README.md +++ b/exercises/05_vecs/README.md @@ -12,6 +12,6 @@ the other useful data structure, hash maps, later. ## Further information -- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html) +- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/book/ch08-01-vectors.html) - [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut) - [`map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map) diff --git a/exercises/12_options/README.md b/exercises/12_options/README.md index bdd33749..624572a3 100644 --- a/exercises/12_options/README.md +++ b/exercises/12_options/README.md @@ -14,7 +14,7 @@ Option types are very common in Rust code, as they have a number of uses: ## Further Information -- [Option Enum Format](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-enum-definitions) +- [Option Enum Format](https://doc.rust-lang.org/book/ch10-01-syntax.html#in-enum-definitions) - [Option Module Documentation](https://doc.rust-lang.org/std/option/) - [Option Enum Documentation](https://doc.rust-lang.org/std/option/enum.Option.html) - [if let](https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html) diff --git a/exercises/14_generics/README.md b/exercises/14_generics/README.md index 72cff3f3..0c8c8cb1 100644 --- a/exercises/14_generics/README.md +++ b/exercises/14_generics/README.md @@ -7,5 +7,5 @@ The simplest and most common use of generics is for type parameters. ## Further information -- [Generic Data Types](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html) +- [Generic Data Types](https://doc.rust-lang.org/book/ch10-01-syntax.html) - [Bounds](https://doc.rust-lang.org/rust-by-example/generics/bounds.html) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index c9fc65aa..846b7868 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -309,7 +309,7 @@ In Rust, there are two ways to define a Vector. inside the square brackets. This way is simpler when you exactly know the initial values. -Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html +Check this chapter: https://doc.rust-lang.org/book/ch08-01-vectors.html of the Rust book to learn more.""" [[exercises]] @@ -378,7 +378,7 @@ dir = "06_move_semantics" test = false hint = """ To find the answer, you can consult the book section "References and Borrowing": -https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html +https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html The first problem is that `get_char` is taking ownership of the string. So `data` is moved and can't be used for `string_uppercase`. `data` is moved to @@ -416,7 +416,7 @@ to its fields. There are however some shortcuts that can be taken when instantiating structs. Have a look in The Book to find out more: -https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax""" +https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax""" [[exercises]] name = "structs3" @@ -487,7 +487,7 @@ to add one character to the `if` statement, though, that will coerce the Side note: If you're interested in learning about how this kind of reference conversion works, you can jump ahead in the book and read this part in the smart pointers chapter: -https://doc.rust-lang.org/stable/book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods""" +https://doc.rust-lang.org/book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods""" [[exercises]] name = "strings3" @@ -561,7 +561,7 @@ hint = """ Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this. Learn more in The Book: -https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value""" +https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value""" [[exercises]] name = "hashmaps3" @@ -572,7 +572,7 @@ Hint 1: Use the `entry()` and `or_insert()` (or `or_insert_with()`) methods of exist in the table yet. Learn more in The Book: -https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value +https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value Hint 2: If there is already an entry for a given key, the value returned by `entry()` can be updated based on the existing value. @@ -739,7 +739,7 @@ name = "generics2" dir = "14_generics" hint = """ Related section in The Book: -https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-method-definitions""" +https://doc.rust-lang.org/book/ch10-01-syntax.html#in-method-definitions""" # TRAITS @@ -871,7 +871,7 @@ We expect the method `Rectangle::new` to panic for negative values. To handle that, you need to add a special attribute to the test function. You can refer to the docs: -https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic""" +https://doc.rust-lang.org/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic""" # STANDARD LIBRARY TYPES @@ -1007,7 +1007,7 @@ thread-local copy of the numbers. This is a simple exercise if you understand the underlying concepts, but if this is too much of a struggle, consider reading through all of Chapter 16 in The Book: -https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html""" +https://doc.rust-lang.org/book/ch16-00-concurrency.html""" [[exercises]] name = "cow1" From 01343f187b0541ab2e210f831c56ef9103ce8c60 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 16:29:43 +0200 Subject: [PATCH 07/29] Explain what a factorial is and link to wikipedia for more details --- exercises/18_iterators/iterators4.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/exercises/18_iterators/iterators4.rs b/exercises/18_iterators/iterators4.rs index 8381dbb1..c296f0e4 100644 --- a/exercises/18_iterators/iterators4.rs +++ b/exercises/18_iterators/iterators4.rs @@ -1,5 +1,8 @@ fn factorial(num: u64) -> u64 { - // TODO: Complete this function to return the factorial of `num`. + // TODO: Complete this function to return the factorial of `num` which is + // defined as `1 * 2 * 3 * … * num`. + // https://en.wikipedia.org/wiki/Factorial + // // Do not use: // - early returns (using the `return` keyword explicitly) // Try not to use: From c793416495b3e015cbd4fb5ea23070aad8611614 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 8 Jul 2024 16:50:35 +0200 Subject: [PATCH 08/29] Fix typo --- rustlings-macros/info.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index 846b7868..a3007c9c 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -585,7 +585,7 @@ https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-value-based-on- [[exercises]] name = "quiz2" dir = "quizzes" -hint = "The `+` operator can concatinate a `String` with a `&str`." +hint = "The `+` operator can concatenate a `String` with a `&str`." # OPTIONS @@ -750,7 +750,7 @@ hint = """ More about traits in The Book: https://doc.rust-lang.org/book/ch10-02-traits.html -The `+` operator can concatinate a `String` with a `&str`.""" +The `+` operator can concatenate a `String` with a `&str`.""" [[exercises]] name = "traits2" From b12b652a57d1e207bef4538e890ddd0ff7ed0a78 Mon Sep 17 00:00:00 2001 From: Jan Arends Date: Wed, 10 Jul 2024 11:16:35 +0200 Subject: [PATCH 09/29] updated variable name in hint --- rustlings-macros/info.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index a3007c9c..67d50e63 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -890,9 +890,9 @@ hint = """ `capitalize_first`: The variable `first` is a `char`. It needs to be capitalized and added to the -remaining characters in `c` in order to return the correct `String`. +remaining characters in `chars` in order to return the correct `String`. -The remaining characters in `c` can be viewed as a string slice using the +The remaining characters in `chars` can be viewed as a string slice using the `as_str` method. The documentation for `char` contains many useful methods. From e512928df57d84bd09a1d630fdafa68a1eef928d Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 10 Jul 2024 13:27:32 +0200 Subject: [PATCH 10/29] Update deps --- Cargo.lock | 46 +++++++++++++++++++--------------------------- Cargo.toml | 6 +++--- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5da969cc..9705c655 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,9 +151,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", "clap_derive", @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -354,15 +354,6 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -594,7 +585,7 @@ dependencies = [ "cassowary", "compact_str", "crossterm", - "itertools 0.13.0", + "itertools", "lru", "paste", "stability", @@ -709,18 +700,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -785,9 +776,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "stability" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", "syn", @@ -829,9 +820,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" dependencies = [ "proc-macro2", "quote", @@ -855,9 +846,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ "indexmap", "serde", @@ -880,11 +871,12 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-truncate" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.12.1", + "itertools", + "unicode-segmentation", "unicode-width", ] diff --git a/Cargo.toml b/Cargo.toml index 22141144..c25f085a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,8 +20,8 @@ license = "MIT" edition = "2021" [workspace.dependencies] -serde = { version = "1.0.203", features = ["derive"] } -toml_edit = { version = "0.22.14", default-features = false, features = ["parse", "serde"] } +serde = { version = "1.0.204", features = ["derive"] } +toml_edit = { version = "0.22.15", default-features = false, features = ["parse", "serde"] } [package] name = "rustlings" @@ -47,7 +47,7 @@ include = [ [dependencies] anyhow = "1.0.86" -clap = { version = "4.5.8", features = ["derive"] } +clap = { version = "4.5.9", features = ["derive"] } crossterm = "0.27.0" hashbrown = "0.14.5" notify-debouncer-mini = { version = "0.4.1", default-features = false } From 59d6b852afd81385020f2b59ab95c85af6229763 Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 10 Jul 2024 13:47:33 +0200 Subject: [PATCH 11/29] move_semantics5: Move `main` to the end --- exercises/06_move_semantics/move_semantics5.rs | 16 ++++++++-------- solutions/06_move_semantics/move_semantics5.rs | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/exercises/06_move_semantics/move_semantics5.rs b/exercises/06_move_semantics/move_semantics5.rs index fc593387..cd0dafd0 100644 --- a/exercises/06_move_semantics/move_semantics5.rs +++ b/exercises/06_move_semantics/move_semantics5.rs @@ -3,14 +3,6 @@ // TODO: Fix the compiler errors without changing anything except adding or // removing references (the character `&`). -fn main() { - let data = "Rust is great!".to_string(); - - get_char(data); - - string_uppercase(&data); -} - // Shouldn't take ownership fn get_char(data: String) -> char { data.chars().last().unwrap() @@ -22,3 +14,11 @@ fn string_uppercase(mut data: &String) { println!("{data}"); } + +fn main() { + let data = "Rust is great!".to_string(); + + get_char(data); + + string_uppercase(&data); +} diff --git a/solutions/06_move_semantics/move_semantics5.rs b/solutions/06_move_semantics/move_semantics5.rs index 678ec97b..1410e913 100644 --- a/solutions/06_move_semantics/move_semantics5.rs +++ b/solutions/06_move_semantics/move_semantics5.rs @@ -1,13 +1,5 @@ #![allow(clippy::ptr_arg)] -fn main() { - let data = "Rust is great!".to_string(); - - get_char(&data); - - string_uppercase(data); -} - // Borrows instead of taking ownership. // It is recommended to use `&str` instead of `&String` here. But this is // enough for now because we didn't handle strings yet. @@ -21,3 +13,11 @@ fn string_uppercase(mut data: String) { println!("{data}"); } + +fn main() { + let data = "Rust is great!".to_string(); + + get_char(&data); + + string_uppercase(data); +} From d7024d80ce0a640271d006dbfda440f60652af6d Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 10 Jul 2024 13:50:39 +0200 Subject: [PATCH 12/29] move_semantics4: Avoid using the dereference operator --- exercises/06_move_semantics/move_semantics4.rs | 8 ++++---- solutions/06_move_semantics/move_semantics4.rs | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/exercises/06_move_semantics/move_semantics4.rs b/exercises/06_move_semantics/move_semantics4.rs index 83a03440..56da988c 100644 --- a/exercises/06_move_semantics/move_semantics4.rs +++ b/exercises/06_move_semantics/move_semantics4.rs @@ -8,11 +8,11 @@ mod tests { // Don't add, change or remove any line. #[test] fn move_semantics4() { - let mut x = 100; + let mut x = Vec::new(); let y = &mut x; let z = &mut x; - *y += 100; - *z += 1000; - assert_eq!(x, 1200); + y.push(42); + z.push(13); + assert_eq!(x, [42, 13]); } } diff --git a/solutions/06_move_semantics/move_semantics4.rs b/solutions/06_move_semantics/move_semantics4.rs index b7919ac0..64fdd9db 100644 --- a/solutions/06_move_semantics/move_semantics4.rs +++ b/solutions/06_move_semantics/move_semantics4.rs @@ -7,15 +7,15 @@ mod tests { // TODO: Fix the compiler errors only by reordering the lines in the test. // Don't add, change or remove any line. #[test] - fn move_semantics5() { - let mut x = 100; + fn move_semantics4() { + let mut x = Vec::new(); let y = &mut x; // `y` used here. - *y += 100; + y.push(42); // The mutable reference `y` is not used anymore, // therefore a new reference can be created. let z = &mut x; - *z += 1000; - assert_eq!(x, 1200); + z.push(13); + assert_eq!(x, [42, 13]); } } From 6263cb6456d18f142c76ccf69ee0d72ae4db3a8b Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 10 Jul 2024 15:16:49 +0200 Subject: [PATCH 13/29] Add note about iterating over Option --- rustlings-macros/info.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index 67d50e63..d7bb1ca1 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -1145,7 +1145,11 @@ test = false strict_clippy = true hint = """ `for` loops over `Option` values are more clearly expressed as an `if-let` -statement.""" +statement. + +Not required to solve this exercise, but if you are interested in when iterating +over `Option` can be useful, read the following section in the documentation: +https://doc.rust-lang.org/std/option/#iterating-over-option""" [[exercises]] name = "clippy3" From 47ba4502e0a60bf720e4c70ff27150bba2d18f8c Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 10 Jul 2024 15:55:18 +0200 Subject: [PATCH 14/29] move_semantics2: Mention cloning in the hint --- rustlings-macros/info.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index d7bb1ca1..e69834ac 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -351,7 +351,7 @@ We call this "moving" a variable. When we pass `vec0` into `fill_vec`, it's being "moved" into `vec1`, meaning we can't access `vec0` anymore. You could make another, separate version of the data that's in `vec0` and -pass it to `fill_vec` instead.""" +pass it to `fill_vec` instead. This is called cloning in Rust.""" [[exercises]] name = "move_semantics3" From 6d2ea8dae3976076d88e783a01e64d08a68cc04a Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 10 Jul 2024 16:49:36 +0200 Subject: [PATCH 15/29] Update CHANGELOG --- CHANGELOG.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9025d451..80e000a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ + + +## 6.1.0 (2024-07-10) + +#### Added + +- `dev check`: Check that all exercises (including third-party ones) include at least one `TODO` comment. +- `dev check`: Check that all exercises actually fail to run (not already solved). + +#### Changed + +- Make enum variants more consistent between enum exercises. +- `iterators3`: Teach about the possible case of integer overflow during division. + +#### Fixed + +- Exit with a helpful error message on missing/unsupported terminal/TTY. +- Mark the last exercise as done. + ## 6.0.1 (2024-07-04) @@ -64,7 +83,7 @@ This should avoid issues related to the language server or to running exercises, Clippy lints are now shown on all exercises, not only the Clippy exercises 📎 Make Clippy your friend from early on 🥰 -### Third party exercises +### Third-party exercises Rustlings now supports third-party exercises! From 0847b3a4bfeebd0d18578de8f45b7e4571fc6e77 Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 10 Jul 2024 16:51:34 +0200 Subject: [PATCH 16/29] chore: Release --- Cargo.lock | 4 ++-- Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9705c655..3bd74507 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -645,7 +645,7 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rustlings" -version = "6.0.1" +version = "6.1.0" dependencies = [ "anyhow", "assert_cmd", @@ -664,7 +664,7 @@ dependencies = [ [[package]] name = "rustlings-macros" -version = "6.0.1" +version = "6.1.0" dependencies = [ "quote", "serde", diff --git a/Cargo.toml b/Cargo.toml index c25f085a..9198f238 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ exclude = [ ] [workspace.package] -version = "6.0.1" +version = "6.1.0" authors = [ "Liv ", "Mo Bitar ", @@ -53,7 +53,7 @@ hashbrown = "0.14.5" notify-debouncer-mini = { version = "0.4.1", default-features = false } os_pipe = "1.2.0" ratatui = { version = "0.27.0", default-features = false, features = ["crossterm"] } -rustlings-macros = { path = "rustlings-macros", version = "=6.0.1" } +rustlings-macros = { path = "rustlings-macros", version = "=6.1.0" } serde_json = "1.0.120" serde.workspace = true toml_edit.workspace = true From d176ddd27ec88b127c615ae5b662aed7de25a231 Mon Sep 17 00:00:00 2001 From: mo8it Date: Fri, 12 Jul 2024 16:29:41 +0200 Subject: [PATCH 17/29] Improve TODO comment --- exercises/quizzes/quiz2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/quizzes/quiz2.rs b/exercises/quizzes/quiz2.rs index 8ef1342a..2cddba90 100644 --- a/exercises/quizzes/quiz2.rs +++ b/exercises/quizzes/quiz2.rs @@ -26,7 +26,7 @@ enum Command { mod my_module { use super::Command; - // TODO: Complete the function. + // TODO: Complete the function as described above. // pub fn transformer(input: ???) -> ??? { ??? } } From 99fb11cc72ce57966cb23a3f5cae2bd34ee7ab8e Mon Sep 17 00:00:00 2001 From: mo8it Date: Sat, 13 Jul 2024 11:53:59 +0200 Subject: [PATCH 18/29] Update syn --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bd74507..f98f402d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -820,9 +820,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.70" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", From 3e09e509d649cfb97f42e4d8547b4a077caaa520 Mon Sep 17 00:00:00 2001 From: mo8it Date: Sat, 13 Jul 2024 12:00:22 +0200 Subject: [PATCH 19/29] Add section about rustlings not found --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 8c1a101c..064451ae 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,17 @@ After installing Rustlings, run the following command to initialize the `rustlin rustlings init ``` +
+If the command `rustlings` can't be found… (click to expand) + +Cargo installs binaries to the directory `~/.cargo/bin`. +You are probably using Linux and installed Rust using your package manager. +Sadly, these package managers often don't add `~/.cargo/bin` to your `PATH` environment variable. +The solution is to either add it manually or to uninstall Rust from the package manager and isntall it using the official way with `rustup`: +https://www.rust-lang.org/tools/install + +
+ Now, go into the newly initialized directory and launch Rustlings for further instructions on getting started with the exercises: ```bash From 12d1971b0d458045f318927f1ce18bb6808a19c0 Mon Sep 17 00:00:00 2001 From: mo8it Date: Sat, 13 Jul 2024 12:02:39 +0200 Subject: [PATCH 20/29] Update section about command not found --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 064451ae..35463ef1 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,12 @@ rustlings init ```
-If the command `rustlings` can't be found… (click to expand) +If the command rustlings can't be found… (click to expand) + +You are probably using Linux and installed Rust using your package manager. Cargo installs binaries to the directory `~/.cargo/bin`. -You are probably using Linux and installed Rust using your package manager. -Sadly, these package managers often don't add `~/.cargo/bin` to your `PATH` environment variable. +Sadly, package managers often don't add `~/.cargo/bin` to your `PATH` environment variable. The solution is to either add it manually or to uninstall Rust from the package manager and isntall it using the official way with `rustup`: https://www.rust-lang.org/tools/install From 516fcf9168391555aacc7e99f51a99d6a87536c6 Mon Sep 17 00:00:00 2001 From: mo8it Date: Sat, 13 Jul 2024 12:07:52 +0200 Subject: [PATCH 21/29] Update section --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35463ef1..a7f81c12 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,11 @@ You are probably using Linux and installed Rust using your package manager. Cargo installs binaries to the directory `~/.cargo/bin`. Sadly, package managers often don't add `~/.cargo/bin` to your `PATH` environment variable. -The solution is to either add it manually or to uninstall Rust from the package manager and isntall it using the official way with `rustup`: -https://www.rust-lang.org/tools/install + +The solution is to … + +- either add `~/.cargo/bin` manually to `PATH` +- or to uninstall Rust from the package manager and install it using the official way with `rustup`: https://www.rust-lang.org/tools/install
From 2854dc9ab347ae500e2a2fe4b6ec6c785fb5796f Mon Sep 17 00:00:00 2001 From: mo8it Date: Sat, 13 Jul 2024 12:32:23 +0200 Subject: [PATCH 22/29] Update CI and release hook --- .github/workflows/rust.yml | 6 ++++-- release-hook.sh | 9 +++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b68cb1b3..5c423e24 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -23,7 +23,9 @@ jobs: with: globs: "exercises/**/*.md" - name: Run cargo fmt - run: cargo fmt --all -- --check + run: cargo fmt --all --check + - name: Run rustfmt on solutions + run: rustfmt --check --edition 2021 --color always solutions/**/*.rs test: runs-on: ${{ matrix.os }} strategy: @@ -33,7 +35,7 @@ jobs: - uses: actions/checkout@v4 - uses: swatinem/rust-cache@v2 - name: Run cargo test - run: cargo test + run: cargo test --workspace dev-check: runs-on: ubuntu-latest steps: diff --git a/release-hook.sh b/release-hook.sh index 052832f2..f021f193 100755 --- a/release-hook.sh +++ b/release-hook.sh @@ -3,7 +3,12 @@ # Error out if any command fails set -e -cargo run -- dev check typos -cargo outdated -w --exit-code 1 +cargo upgrades + +# Similar to CI +cargo clippy -- --deny warnings +cargo fmt --all --check +rustfmt --check --edition 2021 solutions/**/*.rs cargo test --workspace --all-targets +cargo run -- dev check --require-solutions From 3f06d767b5a11789703e7e00e7922bdcd77ce08a Mon Sep 17 00:00:00 2001 From: Mikkel ALMONTE--RINGAUD Date: Tue, 16 Jul 2024 17:20:26 +0200 Subject: [PATCH 23/29] fix: Lyche becomes Lychee Small typo. --- exercises/11_hashmaps/hashmaps2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/11_hashmaps/hashmaps2.rs b/exercises/11_hashmaps/hashmaps2.rs index 376970d7..e9f53fea 100644 --- a/exercises/11_hashmaps/hashmaps2.rs +++ b/exercises/11_hashmaps/hashmaps2.rs @@ -6,7 +6,7 @@ // must add fruit to the basket so that there is at least one of each kind and // more than 11 in total - we have a lot of mouths to feed. You are not allowed // to insert any more of the fruits that are already in the basket (Apple, -// Mango, and Lyche). +// Mango, and Lychee). use std::collections::HashMap; From 362473dde012e2d703a95297c0aa846805627180 Mon Sep 17 00:00:00 2001 From: mo8it Date: Tue, 16 Jul 2024 18:21:07 +0200 Subject: [PATCH 24/29] Sync exercise and solution --- solutions/11_hashmaps/hashmaps2.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solutions/11_hashmaps/hashmaps2.rs b/solutions/11_hashmaps/hashmaps2.rs index a5e6ef9b..75e6ec2c 100644 --- a/solutions/11_hashmaps/hashmaps2.rs +++ b/solutions/11_hashmaps/hashmaps2.rs @@ -5,7 +5,8 @@ // Apple (4), Mango (2) and Lychee (5) are already in the basket hash map. You // must add fruit to the basket so that there is at least one of each kind and // more than 11 in total - we have a lot of mouths to feed. You are not allowed -// to insert any more of these fruits! +// to insert any more of the fruits that are already in the basket (Apple, +// Mango, and Lychee). use std::collections::HashMap; From 2c79e29483b485e6dffd386e8c7e8f7131e33c37 Mon Sep 17 00:00:00 2001 From: yapjiahong Date: Wed, 17 Jul 2024 00:43:42 +0800 Subject: [PATCH 25/29] doc: enchane string3 exercise hint --- rustlings-macros/info.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index e69834ac..9f6616b7 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -498,7 +498,11 @@ some of them: https://doc.rust-lang.org/std/string/struct.String.html#method.trim For the `compose_me` method: You can either use the `format!` macro, or convert -the string slice into an owned string, which you can then freely extend.""" +the string slice into an owned string, which you can then freely extend. + +For the `replace_me` method: You can reference: +https://doc.rust-lang.org/std/string/struct.String.html#method.replace +""" [[exercises]] name = "strings4" From 447ac3c40beed9b5447433c0404ed04a1a38afd8 Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 17 Jul 2024 14:32:45 +0200 Subject: [PATCH 26/29] strings3: Improve hint --- rustlings-macros/info.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index 9f6616b7..2ecb2264 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -500,9 +500,8 @@ https://doc.rust-lang.org/std/string/struct.String.html#method.trim For the `compose_me` method: You can either use the `format!` macro, or convert the string slice into an owned string, which you can then freely extend. -For the `replace_me` method: You can reference: -https://doc.rust-lang.org/std/string/struct.String.html#method.replace -""" +For the `replace_me` method, you can check out the `replace` method: +https://doc.rust-lang.org/std/string/struct.String.html#method.replace""" [[exercises]] name = "strings4" From 183ed3f88f416816312595fde2573b587fd8d999 Mon Sep 17 00:00:00 2001 From: mo8it Date: Wed, 17 Jul 2024 14:33:29 +0200 Subject: [PATCH 27/29] Update dep --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f98f402d..4e05a10c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -516,7 +516,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.5.3", "smallvec", "windows-targets 0.52.6", ] @@ -607,9 +607,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags 2.6.0", ] From 82409c060fb8c5a7763c0e7480d8814e1f994ac8 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 22 Jul 2024 12:01:41 +0200 Subject: [PATCH 28/29] Update deps --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e05a10c..f3824f16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -820,9 +820,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -846,9 +846,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.15" +version = "0.22.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" +checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" dependencies = [ "indexmap", "serde", @@ -1095,9 +1095,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 9198f238..f5fe7380 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ edition = "2021" [workspace.dependencies] serde = { version = "1.0.204", features = ["derive"] } -toml_edit = { version = "0.22.15", default-features = false, features = ["parse", "serde"] } +toml_edit = { version = "0.22.16", default-features = false, features = ["parse", "serde"] } [package] name = "rustlings" From 5116a812fbcdf8662934ef35e5d6d0d0794a5d47 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 22 Jul 2024 12:02:59 +0200 Subject: [PATCH 29/29] tests3: Fix panic message --- exercises/17_tests/tests3.rs | 2 +- solutions/17_tests/tests3.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/17_tests/tests3.rs b/exercises/17_tests/tests3.rs index ec994792..822184ef 100644 --- a/exercises/17_tests/tests3.rs +++ b/exercises/17_tests/tests3.rs @@ -9,7 +9,7 @@ impl Rectangle { if width <= 0 || height <= 0 { // Returning a `Result` would be better here. But we want to learn // how to test functions that can panic. - panic!("Rectangle width and height can't be negative"); + panic!("Rectangle width and height must be positive"); } Rectangle { width, height } diff --git a/solutions/17_tests/tests3.rs b/solutions/17_tests/tests3.rs index 503f9bc0..487fdc66 100644 --- a/solutions/17_tests/tests3.rs +++ b/solutions/17_tests/tests3.rs @@ -9,7 +9,7 @@ impl Rectangle { if width <= 0 || height <= 0 { // Returning a `Result` would be better here. But we want to learn // how to test functions that can panic. - panic!("Rectangle width and height can't be negative"); + panic!("Rectangle width and height must be positive"); } Rectangle { width, height }