diff --git a/.all-contributorsrc b/.all-contributorsrc
index 94141140..049d0f57 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -1713,6 +1713,96 @@
"contributions": [
"content"
]
+ },
+ {
+ "login": "HerschelW",
+ "name": "Kent Worthington",
+ "avatar_url": "https://avatars.githubusercontent.com/u/17935816?v=4",
+ "profile": "https://github.com/HerschelW",
+ "contributions": [
+ "content"
+ ]
+ },
+ {
+ "login": "seporterfield",
+ "name": "seporterfield",
+ "avatar_url": "https://avatars.githubusercontent.com/u/107010978?v=4",
+ "profile": "https://github.com/seporterfield",
+ "contributions": [
+ "content"
+ ]
+ },
+ {
+ "login": "dbarrosop",
+ "name": "David Barroso",
+ "avatar_url": "https://avatars.githubusercontent.com/u/6246622?v=4",
+ "profile": "https://www.linkedin.com/in/dbarrosop",
+ "contributions": [
+ "infra"
+ ]
+ },
+ {
+ "login": "tklauser",
+ "name": "Tobias Klauser",
+ "avatar_url": "https://avatars.githubusercontent.com/u/539708?v=4",
+ "profile": "https://distanz.ch",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "0xMySt1c",
+ "name": "0xMySt1c",
+ "avatar_url": "https://avatars.githubusercontent.com/u/101825630?v=4",
+ "profile": "https://github.com/0xMySt1c",
+ "contributions": [
+ "tool"
+ ]
+ },
+ {
+ "login": "AxolotlTears",
+ "name": "Ten",
+ "avatar_url": "https://avatars.githubusercontent.com/u/87157047?v=4",
+ "profile": "https://github.com/AxolotlTears",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "h4x5p4c3",
+ "name": "jones martin",
+ "avatar_url": "https://avatars.githubusercontent.com/u/66133688?v=4",
+ "profile": "http://h4x5p4c3.xyz",
+ "contributions": [
+ "content"
+ ]
+ },
+ {
+ "login": "cloppingemu",
+ "name": "cloppingemu",
+ "avatar_url": "https://avatars.githubusercontent.com/u/12227963?v=4",
+ "profile": "https://github.com/cloppingemu",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "kevwan",
+ "name": "Kevin Wan",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1918356?v=4",
+ "profile": "http://github.com/zeromicro/go-zero",
+ "contributions": [
+ "content"
+ ]
+ },
+ {
+ "login": "wjwrh",
+ "name": "Ruby",
+ "avatar_url": "https://avatars.githubusercontent.com/u/43495006?v=4",
+ "profile": "http://kurowasaruby.cn",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 8,
diff --git a/.gitpod.yml b/.gitpod.yml
index 73cb802d..06919335 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -4,4 +4,4 @@ tasks:
vscode:
extensions:
- - rust-lang.rust@0.7.8
+ - rust-lang.rust-analyzer@0.3.1348
diff --git a/AUTHORS.md b/AUTHORS.md
index 2fc637f2..e978f1ac 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -11,239 +11,251 @@ authors.
diff --git a/exercises/README.md b/exercises/README.md
index e52137ca..c7effa95 100644
--- a/exercises/README.md
+++ b/exercises/README.md
@@ -7,7 +7,7 @@
| if | Β§3.5 |
| primitive_types | Β§3.2, Β§4.3 |
| vecs | Β§8.1 |
-| move_semantics | Β§4.1, Β§4.2 |
+| move_semantics | Β§4.1-2 |
| structs | Β§5.1, Β§5.3 |
| enums | Β§6, Β§18.3 |
| strings | Β§8.2 |
@@ -19,8 +19,9 @@
| traits | Β§10.2 |
| tests | Β§11.1 |
| lifetimes | Β§10.3 |
-| standard_library_types | Β§13.2, Β§15.1, Β§16.3 |
-| threads | Β§16.1, Β§16.2, Β§16.3 |
+| iterators | Β§13.2-4 |
+| threads | Β§16.1-3 |
+| smart_pointers | Β§15, Β§16.3 |
| macros | Β§19.6 |
-| clippy | n/a |
+| clippy | Β§21.4 |
| conversions | n/a |
diff --git a/exercises/enums/enums3.rs b/exercises/enums/enums3.rs
index 90f91595..8fc49188 100644
--- a/exercises/enums/enums3.rs
+++ b/exercises/enums/enums3.rs
@@ -47,6 +47,7 @@ impl State {
Message::Quit => self.quit(),
_ => ()
}
+
}
}
@@ -63,6 +64,7 @@ mod tests {
};
state.process(Message::ChangeColor((255, 0, 255))); // Remember: The extra parentheses mark a tuple type.
+
state.process(Message::Echo(String::from("hello world")));
state.process(Message::Move(Point { x: 10, y: 15 }));
state.process(Message::Quit);
diff --git a/exercises/iterators/README.md b/exercises/iterators/README.md
new file mode 100644
index 00000000..0e8b671e
--- /dev/null
+++ b/exercises/iterators/README.md
@@ -0,0 +1,8 @@
+# Iterators
+
+This section will teach you about Iterators.
+
+## Further information
+
+- [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html)
+- [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/)
diff --git a/exercises/standard_library_types/iterators1.rs b/exercises/iterators/iterators1.rs
similarity index 100%
rename from exercises/standard_library_types/iterators1.rs
rename to exercises/iterators/iterators1.rs
diff --git a/exercises/standard_library_types/iterators2.rs b/exercises/iterators/iterators2.rs
similarity index 100%
rename from exercises/standard_library_types/iterators2.rs
rename to exercises/iterators/iterators2.rs
diff --git a/exercises/standard_library_types/iterators3.rs b/exercises/iterators/iterators3.rs
similarity index 100%
rename from exercises/standard_library_types/iterators3.rs
rename to exercises/iterators/iterators3.rs
diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/iterators/iterators4.rs
similarity index 100%
rename from exercises/standard_library_types/iterators4.rs
rename to exercises/iterators/iterators4.rs
diff --git a/exercises/standard_library_types/iterators5.rs b/exercises/iterators/iterators5.rs
similarity index 100%
rename from exercises/standard_library_types/iterators5.rs
rename to exercises/iterators/iterators5.rs
diff --git a/exercises/smart_pointers/README.md b/exercises/smart_pointers/README.md
new file mode 100644
index 00000000..c517ae31
--- /dev/null
+++ b/exercises/smart_pointers/README.md
@@ -0,0 +1,11 @@
+# Smart Pointers
+In Rust, smart pointers are variables that contain an address in memory and reference some other data, but they also have additional metadata and capabilities.
+Smart pointers in Rust often own the data they point to, while references only borrow data.
+
+## Further Information
+
+- [Smart Pointers](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html)
+- [Using Box to Point to Data on the Heap](https://doc.rust-lang.org/book/ch15-01-box.html)
+- [Rc\, the Reference Counted Smart Pointer](https://doc.rust-lang.org/book/ch15-04-rc.html)
+- [Shared-State Concurrency](https://doc.rust-lang.org/book/ch16-03-shared-state.html)
+- [Cow Documentation](https://doc.rust-lang.org/std/borrow/enum.Cow.html)
diff --git a/exercises/standard_library_types/arc1.rs b/exercises/smart_pointers/arc1.rs
similarity index 100%
rename from exercises/standard_library_types/arc1.rs
rename to exercises/smart_pointers/arc1.rs
diff --git a/exercises/standard_library_types/box1.rs b/exercises/smart_pointers/box1.rs
similarity index 100%
rename from exercises/standard_library_types/box1.rs
rename to exercises/smart_pointers/box1.rs
diff --git a/exercises/standard_library_types/cow1.rs b/exercises/smart_pointers/cow1.rs
similarity index 100%
rename from exercises/standard_library_types/cow1.rs
rename to exercises/smart_pointers/cow1.rs
diff --git a/exercises/standard_library_types/rc1.rs b/exercises/smart_pointers/rc1.rs
similarity index 99%
rename from exercises/standard_library_types/rc1.rs
rename to exercises/smart_pointers/rc1.rs
index 9b907fde..d62f3619 100644
--- a/exercises/standard_library_types/rc1.rs
+++ b/exercises/smart_pointers/rc1.rs
@@ -6,6 +6,7 @@
// Make this code compile by using the proper Rc primitives to express that the sun has multiple owners.
// I AM NOT DONE
+
use std::rc::Rc;
#[derive(Debug)]
diff --git a/exercises/standard_library_types/README.md b/exercises/standard_library_types/README.md
deleted file mode 100644
index 809d61fe..00000000
--- a/exercises/standard_library_types/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Standard library types
-
-This section will teach you about Box, Shared-State Concurrency and Iterators.
-
-## Further information
-
-- [Using Box to Point to Data on the Heap](https://doc.rust-lang.org/book/ch15-01-box.html)
-- [Shared-State Concurrency](https://doc.rust-lang.org/book/ch16-03-shared-state.html)
-- [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html)
-- [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/)
diff --git a/flake.nix b/flake.nix
index a6703199..2c29ffa5 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,11 +14,18 @@
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
+
+ cargoBuildInputs = with pkgs; lib.optionals stdenv.isDarwin [
+ darwin.apple_sdk.frameworks.CoreServices
+ ];
+
rustlings =
pkgs.rustPlatform.buildRustPackage {
name = "rustlings";
version = "5.3.0";
+ buildInputs = cargoBuildInputs;
+
src = with pkgs.lib; cleanSourceWith {
src = self;
# a function that returns a bool determining if the path should be included in the cleaned source
@@ -42,12 +49,16 @@
in
{
devShell = pkgs.mkShell {
+ RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
+
buildInputs = with pkgs; [
cargo
rustc
rust-analyzer
rustlings
- ];
+ rustfmt
+ clippy
+ ] ++ cargoBuildInputs;
};
});
}
diff --git a/info.toml b/info.toml
index 4b878193..7418943b 100644
--- a/info.toml
+++ b/info.toml
@@ -665,7 +665,7 @@ name = "generics1"
path = "exercises/generics/generics1.rs"
mode = "compile"
hint = """
-Vectors in rust make use of generics to create dynamically sized arrays of any type.
+Vectors in Rust make use of generics to create dynamically sized arrays of any type.
You need to tell the compiler what type we are pushing onto this vector."""
[[exercises]]
@@ -809,13 +809,13 @@ If you use a lifetime annotation in a struct's fields, where else does it need t
[[exercises]]
name = "iterators1"
-path = "exercises/standard_library_types/iterators1.rs"
+path = "exercises/iterators/iterators1.rs"
mode = "compile"
hint = """
Step 1:
We need to apply something to the collection `my_fav_fruits` before we start to go through
it. What could that be? Take a look at the struct definition for a vector for inspiration:
-https://doc.rust-lang.org/std/vec/struct.Vec.html.
+https://doc.rust-lang.org/std/vec/struct.Vec.html
Step 2 & step 3:
Very similar to the lines above and below. You've got this!
Step 4:
@@ -826,7 +826,7 @@ https://doc.rust-lang.org/std/iter/trait.Iterator.html for some ideas.
[[exercises]]
name = "iterators2"
-path = "exercises/standard_library_types/iterators2.rs"
+path = "exercises/iterators/iterators2.rs"
mode = "test"
hint = """
Step 1
@@ -847,7 +847,7 @@ and very general. Rust just needs to know the desired type."""
[[exercises]]
name = "iterators3"
-path = "exercises/standard_library_types/iterators3.rs"
+path = "exercises/iterators/iterators3.rs"
mode = "test"
hint = """
The divide function needs to return the correct error when even division is not
@@ -866,7 +866,7 @@ can make the solution to this exercise infinitely easier."""
[[exercises]]
name = "iterators4"
-path = "exercises/standard_library_types/iterators4.rs"
+path = "exercises/iterators/iterators4.rs"
mode = "test"
hint = """
In an imperative language, you might write a for loop that updates
@@ -878,7 +878,7 @@ Hint 2: Check out the `fold` and `rfold` methods!"""
[[exercises]]
name = "iterators5"
-path = "exercises/standard_library_types/iterators5.rs"
+path = "exercises/iterators/iterators5.rs"
mode = "test"
hint = """
The documentation for the std::iter::Iterator trait contains numerous methods
@@ -895,66 +895,6 @@ The fold method can be useful in the count_collection_iterator function.
For a further challenge, consult the documentation for Iterator to find
a different method that could make your code more compact than using fold."""
-[[exercises]]
-name = "box1"
-path = "exercises/standard_library_types/box1.rs"
-mode = "test"
-hint = """
-Step 1
-The compiler's message should help: since we cannot store the value of the actual type
-when working with recursive types, we need to store a reference (pointer) to its value.
-We should, therefore, place our `List` inside a `Box`. More details in the book here:
-https://doc.rust-lang.org/book/ch15-01-box.html#enabling-recursive-types-with-boxes
-
-Step 2
-Creating an empty list should be fairly straightforward (hint: peek at the assertions).
-For a non-empty list keep in mind that we want to use our Cons "list builder".
-Although the current list is one of integers (i32), feel free to change the definition
-and try other types!
-"""
-
-[[exercises]]
-name = "arc1"
-path = "exercises/standard_library_types/arc1.rs"
-mode = "compile"
-hint = """
-Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order
-to avoid creating a copy of `numbers`, you'll need to create `child_numbers`
-inside the loop but still in the main thread.
-
-`child_numbers` should be a clone of the Arc of the numbers instead of a
-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
-"""
-
-[[exercises]]
-name = "rc1"
-path = "exercises/standard_library_types/rc1.rs"
-mode = "compile"
-hint = """
-This is a straightforward exercise to use the Rc type. Each Planet has
-ownership of the Sun, and uses Rc::clone() to increment the reference count of the Sun.
-After using drop() to move the Planets out of scope individually, the reference count goes down.
-In the end the sun only has one reference again, to itself. See more at:
-https://doc.rust-lang.org/book/ch15-04-rc.html
-
-* Unfortunately Pluto is no longer considered a planet :(
-"""
-
-[[exercises]]
-name = "cow1"
-path = "exercises/standard_library_types/cow1.rs"
-mode = "compile"
-hint = """
-Since the vector is already owned, the `Cow` type doesn't need to clone it.
-
-Checkout https://doc.rust-lang.org/std/borrow/enum.Cow.html for documentation
-on the `Cow` type.
-"""
-
# THREADS
[[exercises]]
@@ -1016,6 +956,68 @@ of the original sending end.
See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info.
"""
+# SMART POINTERS
+
+[[exercises]]
+name = "box1"
+path = "exercises/smart_pointers/box1.rs"
+mode = "test"
+hint = """
+Step 1
+The compiler's message should help: since we cannot store the value of the actual type
+when working with recursive types, we need to store a reference (pointer) to its value.
+We should, therefore, place our `List` inside a `Box`. More details in the book here:
+https://doc.rust-lang.org/book/ch15-01-box.html#enabling-recursive-types-with-boxes
+
+Step 2
+Creating an empty list should be fairly straightforward (hint: peek at the assertions).
+For a non-empty list keep in mind that we want to use our Cons "list builder".
+Although the current list is one of integers (i32), feel free to change the definition
+and try other types!
+"""
+
+[[exercises]]
+name = "rc1"
+path = "exercises/smart_pointers/rc1.rs"
+mode = "compile"
+hint = """
+This is a straightforward exercise to use the Rc type. Each Planet has
+ownership of the Sun, and uses Rc::clone() to increment the reference count of the Sun.
+After using drop() to move the Planets out of scope individually, the reference count goes down.
+In the end the sun only has one reference again, to itself. See more at:
+https://doc.rust-lang.org/book/ch15-04-rc.html
+
+* Unfortunately Pluto is no longer considered a planet :(
+"""
+
+[[exercises]]
+name = "arc1"
+path = "exercises/smart_pointers/arc1.rs"
+mode = "compile"
+hint = """
+Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order
+to avoid creating a copy of `numbers`, you'll need to create `child_numbers`
+inside the loop but still in the main thread.
+
+`child_numbers` should be a clone of the Arc of the numbers instead of a
+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
+"""
+
+[[exercises]]
+name = "cow1"
+path = "exercises/smart_pointers/cow1.rs"
+mode = "compile"
+hint = """
+Since the vector is already owned, the `Cow` type doesn't need to clone it.
+
+Checkout https://doc.rust-lang.org/std/borrow/enum.Cow.html for documentation
+on the `Cow` type.
+"""
+
# MACROS
[[exercises]]
@@ -1070,8 +1072,8 @@ name = "clippy1"
path = "exercises/clippy/clippy1.rs"
mode = "clippy"
hint = """
-Rust stores the highest precision version of any long or inifinite precision
-mathematical constants in the rust standard library.
+Rust stores the highest precision version of any long or infinite precision
+mathematical constants in the Rust standard library.
https://doc.rust-lang.org/stable/std/f32/consts/index.html
We may be tempted to use our own approximations for certain mathematical constants,
diff --git a/src/exercise.rs b/src/exercise.rs
index c0dae34e..2cde4e15 100644
--- a/src/exercise.rs
+++ b/src/exercise.rs
@@ -8,6 +8,7 @@ use std::path::PathBuf;
use std::process::{self, Command};
const RUSTC_COLOR_ARGS: &[&str] = &["--color", "always"];
+const RUSTC_EDITION_ARGS: &[&str] = &["--edition", "2021"];
const I_AM_DONE_REGEX: &str = r"(?m)^\s*///?\s*I\s+AM\s+NOT\s+DONE";
const CONTEXT: usize = 2;
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/clippy/Cargo.toml";
@@ -111,10 +112,12 @@ impl Exercise {
Mode::Compile => Command::new("rustc")
.args(&[self.path.to_str().unwrap(), "-o", &temp_file()])
.args(RUSTC_COLOR_ARGS)
+ .args(RUSTC_EDITION_ARGS)
.output(),
Mode::Test => Command::new("rustc")
.args(&["--test", self.path.to_str().unwrap(), "-o", &temp_file()])
.args(RUSTC_COLOR_ARGS)
+ .args(RUSTC_EDITION_ARGS)
.output(),
Mode::Clippy => {
let cargo_toml = format!(
@@ -140,6 +143,7 @@ path = "{}.rs""#,
Command::new("rustc")
.args(&[self.path.to_str().unwrap(), "-o", &temp_file()])
.args(RUSTC_COLOR_ARGS)
+ .args(RUSTC_EDITION_ARGS)
.output()
.expect("Failed to compile!");
// Due to an issue with Clippy, a cargo clean is required to catch all lints.
@@ -154,7 +158,7 @@ path = "{}.rs""#,
Command::new("cargo")
.args(&["clippy", "--manifest-path", CLIPPY_CARGO_TOML_PATH])
.args(RUSTC_COLOR_ARGS)
- .args(&["--", "-D", "warnings","-D","clippy::float_cmp"])
+ .args(&["--", "-D", "warnings", "-D", "clippy::float_cmp"])
.output()
}
}
diff --git a/src/main.rs b/src/main.rs
index 6dc18e8b..59adb418 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -239,7 +239,7 @@ fn main() {
.get_sysroot_src()
.expect("Couldn't find toolchain path, do you have `rustc` installed?");
project
- .exercies_to_json()
+ .exercises_to_json()
.expect("Couldn't parse rustlings exercises files");
if project.crates.is_empty() {
@@ -350,7 +350,7 @@ fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result {
let (tx, rx) = channel();
let should_quit = Arc::new(AtomicBool::new(false));
- let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;
+ let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(1))?;
watcher.watch(Path::new("./exercises"), RecursiveMode::Recursive)?;
clear_screen();
diff --git a/src/project.rs b/src/project.rs
index 0df00b9a..6e483504 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -1,5 +1,6 @@
use glob::glob;
use serde::{Deserialize, Serialize};
+use std::env;
use std::error::Error;
use std::process::Command;
@@ -54,7 +55,7 @@ impl RustAnalyzerProject {
/// Parse the exercises folder for .rs files, any matches will create
/// a new `crate` in rust-project.json which allows rust-analyzer to
/// treat it like a normal binary
- pub fn exercies_to_json(&mut self) -> Result<(), Box> {
+ pub fn exercises_to_json(&mut self) -> Result<(), Box> {
for e in glob("./exercises/**/*")? {
let path = e?.to_string_lossy().to_string();
self.path_to_json(path);
@@ -64,6 +65,12 @@ impl RustAnalyzerProject {
/// Use `rustc` to determine the default toolchain
pub fn get_sysroot_src(&mut self) -> Result<(), Box> {
+ // check if RUST_SRC_PATH is set
+ if let Ok(path) = env::var("RUST_SRC_PATH") {
+ self.sysroot_src = path;
+ return Ok(());
+ }
+
let toolchain = Command::new("rustc")
.arg("--print")
.arg("sysroot")
diff --git a/src/verify.rs b/src/verify.rs
index 97471b8f..cf319e47 100644
--- a/src/verify.rs
+++ b/src/verify.rs
@@ -13,13 +13,15 @@ pub fn verify<'a>(
progress: (usize, usize),
verbose: bool,
) -> Result<(), &'a Exercise> {
- let (num_done, total) = progress;
+ let (mut num_done, total) = progress;
let bar = ProgressBar::new(total as u64);
bar.set_style(ProgressStyle::default_bar()
.template("Progress: [{bar:60.green/red}] {pos}/{len} {msg}")
.progress_chars("#>-")
);
bar.set_position(num_done as u64);
+ bar.set_message(format!("({:.1} %)", 0.));
+
for exercise in exercises {
let compile_result = match exercise.mode {
Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose),
@@ -29,9 +31,10 @@ pub fn verify<'a>(
if !compile_result.unwrap_or(false) {
return Err(exercise);
}
+ num_done += 1;
let percentage = num_done as f32 / total as f32 * 100.0;
- bar.set_message(format!("({:.1} %)", percentage));
bar.inc(1);
+ bar.set_message(format!("({:.1} %)", percentage));
}
Ok(())
}