diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c14e7d7..a802faaf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,45 @@
+
+## 5.5.1 (2023-05-17)
+
+#### Fixed
+
+- Reverted `rust-project.json` path generation due to an upstream `rust-analyzer` fix.
+
+
+## 5.5.0 (2023-05-17)
+
+#### Added
+
+- `strings2`: Added a reference to the book chapter for reference conversion
+- `lifetimes`: Added a link to the lifetimekata project
+- Added a new `tests4` exercises, which teaches about testing for panics
+- Added a `!` prefix command to watch mode that runs an external command
+- Added a `--success-hints` option to watch mode that shows hints on exercise success
+
+#### Changed
+
+- `vecs2`: Renamed iterator variable bindings for clarify
+- `lifetimes`: Changed order of book references
+- `hashmaps2`: Clarified instructions in the todo block
+- Moved lifetime exercises before test exercises (via the recommended book ordering)
+- `options2`: Improved tests for layering options
+- `modules2`: Added more information to the hint
+
+#### Fixed
+
+- `errors2`: Corrected a comment wording
+- `iterators2`: Fixed a spelling mistake in the hint text
+- `variables`: Wrapped the mut keyword with backticks for readability
+- `move_semantics2`: Removed references to line numbers
+- `cow1`: Clarified the `owned_no_mutation` comments
+- `options3`: Changed exercise to panic when no match is found
+- `rustlings lsp` now generates absolute paths, which should fix VSCode `rust-analyzer` usage on Windows
+
+#### Housekeeping
+
+- Added a markdown linter to run on GitHub actions
+- Split quick installation section into two code blocks
+
## 5.4.1 (2023-03-10)
diff --git a/Cargo.lock b/Cargo.lock
index 192a4ac0..a09d98f7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -441,7 +441,7 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "rustlings"
-version = "5.4.1"
+version = "5.5.1"
dependencies = [
"argh",
"assert_cmd",
diff --git a/Cargo.toml b/Cargo.toml
index d22816ca..eca091f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "rustlings"
-version = "5.4.1"
+description = "Small exercises to get you used to reading and writing Rust code!"
+version = "5.5.1"
authors = [
"Liv ",
"Carol (Nichols || Goulding) ",
diff --git a/README.md b/README.md
index be470fdb..12bd3925 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
+
+
# rustlings π¦β€οΈ
+
+
Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages!
_...looking for the old, web-based version of Rustlings? Try [here](https://github.com/rust-lang/rustlings/tree/rustlings-1)_
@@ -36,8 +40,8 @@ This will install Rustlings and give you access to the `rustlings` command. Run
Basically: Clone the repository at the latest tag, finally run `nix develop` or `nix-shell`.
```bash
-# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.4.1)
-git clone -b 5.4.1 --depth 1 https://github.com/rust-lang/rustlings
+# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.5.1)
+git clone -b 5.5.1 --depth 1 https://github.com/rust-lang/rustlings
cd rustlings
# if nix version > 2.3
nix develop
@@ -74,8 +78,8 @@ If you get a permission denied message, you might have to exclude the directory
Basically: Clone the repository at the latest tag, run `cargo install --path .`.
```bash
-# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.4.1)
-git clone -b 5.4.1 --depth 1 https://github.com/rust-lang/rustlings
+# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.5.1)
+git clone -b 5.5.1 --depth 1 https://github.com/rust-lang/rustlings
cd rustlings
cargo install --force --path .
```
diff --git a/exercises/conversions/README.md b/exercises/conversions/README.md
index 8d7da93e..619a78c5 100644
--- a/exercises/conversions/README.md
+++ b/exercises/conversions/README.md
@@ -6,6 +6,7 @@ The simplest form of type conversion is a type cast expression. It is denoted wi
Rust also offers traits that facilitate type conversions upon implementation. These traits can be found under the [`convert`](https://doc.rust-lang.org/std/convert/index.html) module.
The traits are the following:
+
- `From` and `Into` covered in [`from_into`](from_into.rs)
- `TryFrom` and `TryInto` covered in [`try_from_into`](try_from_into.rs)
- `AsRef` and `AsMut` covered in [`as_ref_mut`](as_ref_mut.rs)
@@ -17,5 +18,6 @@ These should be the main ways ***within the standard library*** to convert data
## Further information
These are not directly covered in the book, but the standard library has a great documentation for it.
+
- [conversions](https://doc.rust-lang.org/std/convert/index.html)
-- [`FromStr` trait](https://doc.rust-lang.org/std/str/trait.FromStr.html)
\ No newline at end of file
+- [`FromStr` trait](https://doc.rust-lang.org/std/str/trait.FromStr.html)
diff --git a/exercises/hashmaps/README.md b/exercises/hashmaps/README.md
index 6afa04b2..80ec1441 100644
--- a/exercises/hashmaps/README.md
+++ b/exercises/hashmaps/README.md
@@ -1,4 +1,5 @@
# Hashmaps
+
A *hash map* allows you to associate a value with a particular key.
You may also know this by the names [*unordered map* in C++](https://en.cppreference.com/w/cpp/container/unordered_map),
[*dictionary* in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) or an *associative array* in other languages.
diff --git a/exercises/iterators/iterators5.rs b/exercises/iterators/iterators5.rs
index 0593d123..d0fcc8ca 100644
--- a/exercises/iterators/iterators5.rs
+++ b/exercises/iterators/iterators5.rs
@@ -2,13 +2,11 @@
// Let's define a simple model to track Rustlings exercise progress. Progress
// will be modelled using a hash map. The name of the exercise is the key and
// the progress is the value. Two counting functions were created to count the
-// number of exercises with a given progress. These counting functions use
-// imperative style for loops. Recreate this counting functionality using
-// iterators. Only the two iterator methods (count_iterator and
-// count_collection_iterator) need to be modified.
+// number of exercises with a given progress. Recreate this counting
+// functionality using iterators. Try not to use imperative loops (for, while).
+// Only the two iterator methods (count_iterator and count_collection_iterator)
+// need to be modified.
// Execute `rustlings hint iterators5` or use the `hint` watch subcommand for a hint.
-//
-// Make the code compile and the tests pass.
// I AM NOT DONE
@@ -67,12 +65,27 @@ mod tests {
}
#[test]
- fn count_equals_for() {
+ fn count_some() {
let map = get_map();
- assert_eq!(
- count_for(&map, Progress::Complete),
- count_iterator(&map, Progress::Complete)
- );
+ assert_eq!(1, count_iterator(&map, Progress::Some));
+ }
+
+ #[test]
+ fn count_none() {
+ let map = get_map();
+ assert_eq!(2, count_iterator(&map, Progress::None));
+ }
+
+ #[test]
+ fn count_complete_equals_for() {
+ let map = get_map();
+ let progress_states = vec![Progress::Complete, Progress::Some, Progress::None];
+ for progress_state in progress_states {
+ assert_eq!(
+ count_for(&map, progress_state),
+ count_iterator(&map, progress_state)
+ );
+ }
}
#[test]
@@ -85,12 +98,28 @@ mod tests {
}
#[test]
- fn count_collection_equals_for() {
+ fn count_collection_some() {
let collection = get_vec_map();
- assert_eq!(
- count_collection_for(&collection, Progress::Complete),
- count_collection_iterator(&collection, Progress::Complete)
- );
+ assert_eq!(1, count_collection_iterator(&collection, Progress::Some));
+ }
+
+ #[test]
+ fn count_collection_none() {
+ let collection = get_vec_map();
+ assert_eq!(4, count_collection_iterator(&collection, Progress::None));
+ }
+
+ #[test]
+ fn count_collection_equals_for() {
+ let progress_states = vec![Progress::Complete, Progress::Some, Progress::None];
+ let collection = get_vec_map();
+
+ for progress_state in progress_states {
+ assert_eq!(
+ count_collection_for(&collection, progress_state),
+ count_collection_iterator(&collection, progress_state)
+ );
+ }
}
fn get_map() -> HashMap {
diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs
index 64870850..93bb82ef 100644
--- a/exercises/move_semantics/move_semantics2.rs
+++ b/exercises/move_semantics/move_semantics2.rs
@@ -1,12 +1,16 @@
// move_semantics2.rs
-// Make me compile without changing line 13 or moving line 10!
// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand for a hint.
+// Expected output:
+// vec0 has length 3 content `[22, 44, 66]`
+// vec1 has length 4 content `[22, 44, 66, 88]`
+
// I AM NOT DONE
fn main() {
let vec0 = Vec::new();
+ // Do not move the following line!
let mut vec1 = fill_vec(vec0);
// Do not change the following line!
diff --git a/exercises/options/README.md b/exercises/options/README.md
index 5433fed8..bdd33749 100644
--- a/exercises/options/README.md
+++ b/exercises/options/README.md
@@ -2,6 +2,7 @@
Type Option represents an optional value: every Option is either Some and contains a value, or None, and does not.
Option types are very common in Rust code, as they have a number of uses:
+
- Initial values
- Return values for functions that are not defined over their entire input range (partial functions)
- Return value for otherwise reporting simple errors, where None is returned on error
diff --git a/exercises/options/options2.rs b/exercises/options/options2.rs
index 4e36443f..337c4261 100644
--- a/exercises/options/options2.rs
+++ b/exercises/options/options2.rs
@@ -18,17 +18,22 @@ mod tests {
#[test]
fn layered_option() {
- let mut range = 10;
- let mut optional_integers: Vec