summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exercises/enums/enums1.rs30
-rw-r--r--exercises/enums/enums2.rs37
-rw-r--r--exercises/error_handling/errors1.rs35
-rw-r--r--exercises/error_handling/errors2.rs26
-rw-r--r--exercises/error_handling/errors3.rs22
-rw-r--r--exercises/error_handling/errorsn.rs137
-rw-r--r--exercises/error_handling/option1.rs30
-rw-r--r--exercises/error_handling/result1.rs21
-rw-r--r--exercises/functions/functions1.rs40
-rw-r--r--exercises/functions/functions2.rs32
-rw-r--r--exercises/functions/functions3.rs32
-rw-r--r--exercises/functions/functions4.rs24
-rw-r--r--exercises/functions/functions5.rs38
-rw-r--r--exercises/if/if1.rs35
-rw-r--r--exercises/macros/macros1.rs54
-rw-r--r--exercises/macros/macros2.rs63
-rw-r--r--exercises/macros/macros3.rs64
-rw-r--r--exercises/macros/macros4.rs63
-rw-r--r--exercises/modules/modules1.rs33
-rw-r--r--exercises/modules/modules2.rs24
-rw-r--r--exercises/move_semantics/move_semantics1.rs20
-rw-r--r--exercises/move_semantics/move_semantics2.rs31
-rw-r--r--exercises/move_semantics/move_semantics3.rs23
-rw-r--r--exercises/move_semantics/move_semantics4.rs24
-rw-r--r--exercises/primitive_types/primitive_types3.rs36
-rw-r--r--exercises/primitive_types/primitive_types4.rs58
-rw-r--r--exercises/primitive_types/primitive_types5.rs37
-rw-r--r--exercises/primitive_types/primitive_types6.rs38
-rw-r--r--exercises/standard_library_types/arc1.rs28
-rw-r--r--exercises/standard_library_types/iterators2.rs101
-rw-r--r--exercises/standard_library_types/iterators3.rs72
-rw-r--r--exercises/standard_library_types/iterators4.rs31
-rw-r--r--exercises/strings/strings1.rs38
-rw-r--r--exercises/strings/strings2.rs32
-rw-r--r--exercises/tests/tests1.rs36
-rw-r--r--exercises/tests/tests2.rs35
-rw-r--r--exercises/tests/tests3.rs28
-rw-r--r--exercises/threads/threads1.rs72
-rw-r--r--exercises/variables/variables1.rs37
-rw-r--r--exercises/variables/variables2.rs38
-rw-r--r--exercises/variables/variables3.rs36
-rw-r--r--exercises/variables/variables4.rs40
-rw-r--r--info.toml381
-rw-r--r--src/exercise.rs4
-rw-r--r--src/main.rs39
-rw-r--r--tests/fixture/failure/info.toml6
-rw-r--r--tests/fixture/success/info.toml6
-rw-r--r--tests/integration_tests.rs18
48 files changed, 483 insertions, 1702 deletions
diff --git a/exercises/enums/enums1.rs b/exercises/enums/enums1.rs
index f490928..a2223d3 100644
--- a/exercises/enums/enums1.rs
+++ b/exercises/enums/enums1.rs
@@ -1,5 +1,5 @@
// enums1.rs
-// Make me compile! Scroll down for hints!
+// Make me compile! Execute `rustlings hint enums1` for hints!
// I AM NOT DONE
@@ -14,31 +14,3 @@ fn main() {
println!("{:?}", Message::Move);
println!("{:?}", Message::ChangeColor);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Hint: The declaration of the enumeration type has not been defined yet.
diff --git a/exercises/enums/enums2.rs b/exercises/enums/enums2.rs
index 8f04bd8..52ccb22 100644
--- a/exercises/enums/enums2.rs
+++ b/exercises/enums/enums2.rs
@@ -1,5 +1,5 @@
// enums2.rs
-// Make me compile! Scroll down for hints
+// Make me compile! Execute `rustlings hint enums2` for hints!
// I AM NOT DONE
@@ -26,38 +26,3 @@ fn main() {
message.call();
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Hint: you can create enumerations that have different variants with different types
-// such as no data, anonymous structs, a single string, tuples, ...etc
diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs
index a06f0ca..9c24d85 100644
--- a/exercises/error_handling/errors1.rs
+++ b/exercises/error_handling/errors1.rs
@@ -4,7 +4,7 @@
// was, instead of just sometimes returning `None`. The 2nd test currently
// does not compile or pass, but it illustrates the behavior we would like
// this function to have.
-// Scroll down for hints!!!
+// Execute `rustlings hint errors1` for hints!
// I AM NOT DONE
@@ -40,36 +40,3 @@ mod tests {
);
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// `Err` is one of the variants of `Result`, so what the 2nd test is saying
-// is that `generate_nametag_text` should return a `Result` instead of an
-// `Option`.
-
-// To make this change, you'll need to:
-// - update the return type in the function signature to be a Result<String, String> that
-// could be the variants `Ok(String)` and `Err(String)`
-// - change the body of the function to return `Ok(stuff)` where it currently
-// returns `Some(stuff)`
-// - change the body of the function to return `Err(error message)` where it
-// currently returns `None`
-// - change the first test to expect `Ok(stuff)` where it currently expects
-// `Some(stuff)`.
diff --git a/exercises/error_handling/errors2.rs b/exercises/error_handling/errors2.rs
index 315528f..aad3a93 100644
--- a/exercises/error_handling/errors2.rs
+++ b/exercises/error_handling/errors2.rs
@@ -14,7 +14,7 @@
// and add.
// There are at least two ways to implement this that are both correct-- but
-// one is a lot shorter! Scroll down for hints to both ways.
+// one is a lot shorter! Execute `rustlings hint errors2` for hints to both ways.
// I AM NOT DONE
@@ -45,27 +45,3 @@ mod tests {
);
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// One way to handle this is using a `match` statement on
-// `item_quantity.parse::<i32>()` where the cases are `Ok(something)` and
-// `Err(something)`. This pattern is very common in Rust, though, so there's
-// a `?` operator that does pretty much what you would make that match statement
-// do for you! Take a look at this section of the Error Handling chapter:
-// https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
-// and give it a try!
diff --git a/exercises/error_handling/errors3.rs b/exercises/error_handling/errors3.rs
index 35cd5c3..460ac5c 100644
--- a/exercises/error_handling/errors3.rs
+++ b/exercises/error_handling/errors3.rs
@@ -1,7 +1,8 @@
// errors3.rs
// This is a program that is trying to use a completed version of the
// `total_cost` function from the previous exercise. It's not working though!
-// Why not? What should we do to fix it? Scroll for hints!
+// Why not? What should we do to fix it?
+// Execute `rustlings hint errors3` for hints!
// I AM NOT DONE
@@ -28,22 +29,3 @@ pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
Ok(qty * cost_per_item + processing_fee)
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// If other functions can return a `Result`, why shouldn't `main`?
diff --git a/exercises/error_handling/errorsn.rs b/exercises/error_handling/errorsn.rs
index cc90801..fc25308 100644
--- a/exercises/error_handling/errorsn.rs
+++ b/exercises/error_handling/errorsn.rs
@@ -13,7 +13,7 @@
// type goes where the question marks are, and how do we return
// that type from the body of read_and_validate?
//
-// Scroll down for hints :)
+// Execute `rustlings hint errors4` for hints :)
// I AM NOT DONE
@@ -112,138 +112,3 @@ impl error::Error for CreationError {
}
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// First hint: To figure out what type should go where the ??? is, take a look
-// at the test helper function `test_with_str`, since it returns whatever
-// `read_and_validate` returns and`test_with_str` has its signature fully
-// specified.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Next hint: There are three places in `read_and_validate` that we call a
-// function that returns a `Result` (that is, the functions might fail).
-// Apply the `?` operator on those calls so that we return immediately from
-// `read_and_validate` if those function calls fail.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Another hint: under the hood, the `?` operator calls `From::from`
-// on the error value to convert it to a boxed trait object, a Box<dyn error::Error>,
-// which is polymorphic-- that means that lots of different kinds of errors
-// can be returned from the same function because all errors act the same
-// since they all implement the `error::Error` trait.
-// Check out this section of the book:
-// https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Another another hint: Note that because the `?` operator returns
-// the *unwrapped* value in the `Ok` case, if we want to return a `Result` from
-// `read_and_validate` for *its* success case, we'll have to rewrap a value
-// that we got from the return value of a `?`ed call in an `Ok`-- this will
-// look like `Ok(something)`.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Another another another hint: `Result`s must be "used", that is, you'll
-// get a warning if you don't handle a `Result` that you get in your
-// function. Read more about that in the `std::result` module docs:
-// https://doc.rust-lang.org/std/result/#results-must-be-used
diff --git a/exercises/error_handling/option1.rs b/exercises/error_handling/option1.rs
index 4e432a6..5d81b15 100644
--- a/exercises/error_handling/option1.rs
+++ b/exercises/error_handling/option1.rs
@@ -2,7 +2,7 @@
// This example panics because the second time it calls `pop`, the `vec`
// is empty, so `pop` returns `None`, and `unwrap` panics if it's called
// on `None`. Handle this in a more graceful way than calling `unwrap`!
-// Scroll down for hints :)
+// Execute `rustlings hint option1` for hints :)
// I AM NOT DONE
@@ -29,31 +29,3 @@ mod tests {
assert!(pop_too_much());
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Try using a `match` statement where the arms are `Some(thing)` and `None`.
-// Or set a default value to print out if you get `None` by using the
-// function `unwrap_or`.
-// Or use an `if let` statement on the result of `pop()` to both destructure
-// a `Some` value and only print out something if we have a value!
diff --git a/exercises/error_handling/result1.rs b/exercises/error_handling/result1.rs
index 52972dc..352a6c2 100644
--- a/exercises/error_handling/result1.rs
+++ b/exercises/error_handling/result1.rs
@@ -1,5 +1,5 @@
// result1.rs
-// Make this test pass! Scroll down for hints :)
+// Make this test pass! Execute `rustlings hint option2` for hints :)
// I AM NOT DONE
@@ -27,22 +27,3 @@ fn test_creation() {
);
assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// `PositiveNonzeroInteger::new` is always creating a new instance and returning an `Ok` result.
-// It should be doing some checking, returning an `Err` result if those checks fail, and only
-// returning an `Ok` result if those checks determine that everything is... okay :)
diff --git a/exercises/functions/functions1.rs b/exercises/functions/functions1.rs
index b9312ae..49d48e9 100644
--- a/exercises/functions/functions1.rs
+++ b/exercises/functions/functions1.rs
@@ -1,46 +1,8 @@
// functions1.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint function1` for hints :)
// I AM NOT DONE
fn main() {
call_me();
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// This main function is calling a function that it expects to exist, but the
-// function doesn't exist. It expects this function to have the name `call_me`.
-// It expects this function to not take any arguments and not return a value.
-// Sounds a lot like `main`, doesn't it?
diff --git a/exercises/functions/functions2.rs b/exercises/functions/functions2.rs
index c5b4418..108ba38 100644
--- a/exercises/functions/functions2.rs
+++ b/exercises/functions/functions2.rs
@@ -1,5 +1,5 @@
// functions2.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint functions2` for hints :)
// I AM NOT DONE
@@ -12,33 +12,3 @@ fn call_me(num) {
println!("Ring! Call number {}", i + 1);
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Rust requires that all parts of a function's signature have type annotations,
-// but `call_me` is missing the type annotation of `num`.
diff --git a/exercises/functions/functions3.rs b/exercises/functions/functions3.rs
index 63bb586..e3c1bf7 100644
--- a/exercises/functions/functions3.rs
+++ b/exercises/functions/functions3.rs
@@ -1,5 +1,5 @@
// functions3.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint functions3` for hints :)
// I AM NOT DONE
@@ -12,33 +12,3 @@ fn call_me(num: i32) {
println!("Ring! Call number {}", i + 1);
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// This time, the function *declaration* is okay, but there's something wrong
-// with the place where we're calling the function.
diff --git a/exercises/functions/functions4.rs b/exercises/functions/functions4.rs
index 91f6295..6bf46f0 100644
--- a/exercises/functions/functions4.rs
+++ b/exercises/functions/functions4.rs
@@ -1,5 +1,5 @@
// functions4.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint functions4` for hints :)
// This store is having a sale where if the price is an even number, you get
// 10 (money unit) off, but if it's an odd number, it's 3 (money unit) less.
@@ -22,25 +22,3 @@ fn sale_price(price: i32) -> {
fn is_even(num: i32) -> bool {
num % 2 == 0
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// The error message points to line 12 and says it expects a type after the
-// `->`. This is where the function's return type should be-- take a look at
-// the `is_even` function for an example!
diff --git a/exercises/functions/functions5.rs b/exercises/functions/functions5.rs
index 696edee..d22aa6c 100644
--- a/exercises/functions/functions5.rs
+++ b/exercises/functions/functions5.rs
@@ -1,5 +1,5 @@
// functions5.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint functions5` for hints :)
// I AM NOT DONE
@@ -11,39 +11,3 @@ fn main() {
fn square(num: i32) -> i32 {
num * num;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// This is a really common error that can be fixed by removing one character.
-// It happens because Rust distinguishes between expressions and statements: expressions return
-// a value based on its operand, and statements simply return a () type which behaves just like `void` in C/C++ language.
-// We want to return a value of `i32` type from the `square` function, but it is returning a `()` type...
-// They are not the same. There are two solutions:
-// 1. Add a `return` ahead of `num * num;`
-// 2. remove `;`, make it to be `num * num`
diff --git a/exercises/if/if1.rs b/exercises/if/if1.rs
index da77e35..9086754 100644
--- a/exercises/if/if1.rs
+++ b/exercises/if/if1.rs
@@ -7,7 +7,7 @@ pub fn bigger(a: i32, b: i32) -> i32 {
// Do not use:
// - another function call
// - additional variables
- // Scroll down for hints.
+ // Execute `rustlings hint if1` for hints
}
// Don't mind this for now :)
@@ -25,36 +25,3 @@ mod tests {
assert_eq!(42, bigger(32, 42));
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// It's possible to do this in one line if you would like!
-// Some similar examples from other languages:
-// - In C(++) this would be: `a > b ? a : b`
-// - In Python this would be: `a if a > b else b`
-// Remember in Rust that:
-// - the `if` condition does not need to be surrounded by parentheses
-// - `if`/`else` conditionals are expressions
-// - Each condition is followed by a `{}` block.
diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs
index f7b89e0..ed0dac8 100644
--- a/exercises/macros/macros1.rs
+++ b/exercises/macros/macros1.rs
@@ -1,5 +1,5 @@
// macros1.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint macros1` for hints :)
// I AM NOT DONE
@@ -12,55 +12,3 @@ macro_rules! my_macro {
fn main() {
my_macro();
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// When you call a macro, you need to add something special compared to a
-// regular function call. If you're stuck, take a look at what's inside
-// `my_macro`.
diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs
index 7fe9429..d0be123 100644
--- a/exercises/macros/macros2.rs
+++ b/exercises/macros/macros2.rs
@@ -1,5 +1,5 @@
// macros2.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint macros2` for hints :)
// I AM NOT DONE
@@ -12,64 +12,3 @@ macro_rules! my_macro {
println!("Check out my macro!");
};
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Macros don't quite play by the same rules as the rest of Rust, in terms of
-// what's available where.
-
-
-
-
-
-
-
-
-// Unlike other things in Rust, the order of "where you define a macro" versus
-// "where you use it" actually matters.
diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs
index e9ef7f3..93a4311 100644
--- a/exercises/macros/macros3.rs
+++ b/exercises/macros/macros3.rs
@@ -1,5 +1,6 @@
// macros3.rs
-// Make me compile, without taking the macro out of the module! Scroll down for hints :)
+// Make me compile, without taking the macro out of the module!
+// Execute `rustlings hint macros3` for hints :)
// I AM NOT DONE
@@ -14,64 +15,3 @@ mod macros {
fn main() {
my_macro!();
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// In order to use a macro outside of its module, you need to do something
-// special to the module to lift the macro out into its parent.
-
-
-
-
-
-
-
-
-// The same trick also works on "extern crate" statements for crates that have
-// exported macros, if you've seen any of those around.
diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs
index 2893a15..3a74807 100644
--- a/exercises/macros/macros4.rs
+++ b/exercises/macros/macros4.rs
@@ -1,5 +1,5 @@
// macros4.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint macros4` for hints :)
// I AM NOT DONE
@@ -16,64 +16,3 @@ fn main() {
my_macro!();
my_macro!(7777);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// You only need to add a single character to make this compile.
-
-
-
-
-
-
-
-
-
-// The way macros are written, it wants to see something between each
-// "macro arm", so it can separate them.
diff --git a/exercises/modules/modules1.rs b/exercises/modules/modules1.rs
index 3f44968..812dfee 100644
--- a/exercises/modules/modules1.rs
+++ b/exercises/modules/modules1.rs
@@ -1,5 +1,5 @@
// modules1.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint modules1` for hints :)
// I AM NOT DONE
@@ -12,34 +12,3 @@ mod sausage_factory {
fn main() {
sausage_factory::make_sausage();
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Everything is private in Rust by default-- but there's a keyword we can use
-// to make something public! The compiler error should point to the thing that
-// needs to be public.
diff --git a/exercises/modules/modules2.rs b/exercises/modules/modules2.rs
index a3497cf..fde439d 100644
--- a/exercises/modules/modules2.rs
+++ b/exercises/modules/modules2.rs
@@ -1,5 +1,5 @@
// modules2.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint modules2` for hints :)
// I AM NOT DONE
@@ -25,25 +25,3 @@ fn main() {
delicious_snacks::veggie
);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// The delicious_snacks module is trying to present an external
-// interface (the `fruit` and `veggie` constants) that is different than
-// its internal structure (the `fruits` and `veggies` modules and
-// associated constants). It's almost there except for one keyword missing for
-// each constant.
diff --git a/exercises/move_semantics/move_semantics1.rs b/exercises/move_semantics/move_semantics1.rs
index 625096d..e2f5876 100644
--- a/exercises/move_semantics/move_semantics1.rs
+++ b/exercises/move_semantics/move_semantics1.rs
@@ -1,5 +1,5 @@
// move_semantics1.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute `rustlings hint move_semantics1` for hints :)
// I AM NOT DONE
@@ -24,21 +24,3 @@ fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 11,
-// right? The fix for this is going to be adding one keyword, and the addition is NOT on line 11
-// where the error is.
diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs
index 28749e2..9233bb7 100644
--- a/exercises/move_semantics/move_semantics2.rs
+++ b/exercises/move_semantics/move_semantics2.rs
@@ -1,5 +1,6 @@
// move_semantics2.rs
-// Make me compile without changing line 10! Scroll down for hints :)
+// Make me compile without changing line 10!
+// Execute `rustlings hint move_semantics2` for hints :)
// I AM NOT DONE
@@ -25,31 +26,3 @@ fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// So `vec0` is being *moved* into the function `fill_vec` when we call it on
-// line 7, which means it gets dropped at the end of `fill_vec`, which means we
-// can't use `vec0` again on line 10 (or anywhere else in `main` after the
-// `fill_vec` call for that matter). We could fix this in a few ways, try them
-// all!
-// 1. Make another, separate version of the data that's in `vec0` and pass that
-// to `fill_vec` instead.
-// 2. Make `fill_vec` borrow its argument instead of taking ownership of it,
-// and then copy the data within the function in order to return an owned
-// `Vec<i32>`
-// 3. Make `fill_vec` *mutably* borrow its argument (which will need to be
-// mutable), modify it directly, then not return anything. Then you can get rid
-// of `vec1` entirely -- note that this will change what gets printed by the
-// first `println!`
diff --git a/exercises/move_semantics/move_semantics3.rs b/exercises/move_semantics/move_semantics3.rs
index a5b41b4..43fef74 100644
--- a/exercises/move_semantics/move_semantics3.rs
+++ b/exercises/move_semantics/move_semantics3.rs
@@ -1,7 +1,7 @@
// move_semantics3.rs
// Make me compile without adding new lines-- just changing existing lines!
// (no lines with multiple semicolons necessary!)
-// Scroll down for hints :)
+// Execute `rustlings hint move_semantics3` for hints :)
// I AM NOT DONE
@@ -24,24 +24,3 @@ fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// The difference between this one and the previous ones is that the first line
-// of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can,
-// instead of adding that line back, add `mut` in one place that will change
-// an existing binding to be a mutable binding instead of an immutable one :)
diff --git a/exercises/move_semantics/move_semantics4.rs b/exercises/move_semantics/move_semantics4.rs
index b01e593..a1c4a41 100644
--- a/exercises/move_semantics/move_semantics4.rs
+++ b/exercises/move_semantics/move_semantics4.rs
@@ -1,7 +1,8 @@
// move_semantics4.rs
// Refactor this code so that instead of having `vec0` and creating the vector
// in `fn main`, we instead create it within `fn fill_vec` and transfer the
-// freshly created vector from fill_vec to its caller. Scroll for hints!
+// freshly created vector from fill_vec to its caller.
+// Execute `rustlings hint move_semantics4` for hints!
// I AM NOT DONE
@@ -27,24 +28,3 @@ fn fill_vec() -> Vec<i32> {
vec
}
-
-
-
-
-
-
-
-
-
-
-
-
-// Stop reading whenever you feel like you have enough direction :) Or try
-// doing one step and then fixing the compiler errors that result!
-// So the end goal is to:
-// - get rid of the first line in main that creates the new vector
-// - so then `vec0` doesn't exist, so we can't pass it to `fill_vec`
-// - we don't want to pass anything to `fill_vec`, so its signature should
-// reflect that it does not take any arguments
-// - since we're not creating a new vec in `main` anymore, we need to create
-// a new vec in `fill_vec`, similarly to the way we did in `main`
diff --git a/exercises/primitive_types/primitive_types3.rs b/exercises/primitive_types/primitive_types3.rs
index bf2716a..dfd6351 100644
--- a/exercises/primitive_types/primitive_types3.rs
+++ b/exercises/primitive_types/primitive_types3.rs
@@ -1,6 +1,6 @@
// primitive_types3.rs
// Create an array with at least 100 elements in it where the ??? is.
-// Scroll down for hints!
+// Execute `rustlings hint primitive_types3` for hints!
// I AM NOT DONE
@@ -13,37 +13,3 @@ fn main() {
println!("Meh, I eat arrays like that for breakfast.");
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// There's a shorthand to initialize Arrays with a certain size that does not
-// require you to type in 100 items (but you certainly can if you want!).
-// For example, you can do:
-// let array = ["Are we there yet?"; 10];
-
-// Bonus: what are some other things you could have that would return true
-// for `a.len() >= 100`?
diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs
index e675aa1..ff1e279 100644
--- a/exercises/primitive_types/primitive_types4.rs
+++ b/exercises/primitive_types/primitive_types4.rs
@@ -1,6 +1,6 @@
// primitive_types4.rs
// Get a slice out of Array a where the ??? is so that the `if` statement
-// returns true. Scroll down for hints!!
+// returns true. Execute `rustlings hint primitive_types4` for hints!!
// I AM NOT DONE
@@ -12,59 +12,3 @@ fn main() {
assert_eq!([2, 3, 4], nice_slice)
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book:
-// https://doc.rust-lang.org/book/ch04-03-slices.html
-// and use the starting and ending indices of the items in the Array
-// that you want to end up in the slice.
-
-// If you're curious why the right hand of the `==` comparison does not
-// have an ampersand for a reference since the left hand side is a
-// reference, take a look at the Deref coercions section of the book:
-// https://doc.rust-lang.org/book/ch15-02-deref.html
diff --git a/exercises/primitive_types/primitive_types5.rs b/exercises/primitive_types/primitive_types5.rs
index d8527ee..680d8d2 100644
--- a/exercises/primitive_types/primitive_types5.rs
+++ b/exercises/primitive_types/primitive_types5.rs
@@ -1,6 +1,6 @@
// primitive_types5.rs
// Destructure the `cat` tuple so that the println will work.
-// Scroll down for hints!
+// Execute `rustlings hint primitive_types5` for hints!
// I AM NOT DONE
@@ -10,38 +10,3 @@ fn main() {
println!("{} is {} years old.", name, age);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Take a look at the Data Types -> The Tuple Type section of the book:
-// https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
-// Particularly the part about destructuring (second to last example in the section).
-// You'll need to make a pattern to bind `name` and `age` to the appropriate parts
-// of the tuple. You can do it!!
diff --git a/exercises/primitive_types/primitive_types6.rs b/exercises/primitive_types/primitive_types6.rs
index 8fe9a36..2bc817e 100644
--- a/exercises/primitive_types/primitive_types6.rs
+++ b/exercises/primitive_types/primitive_types6.rs
@@ -1,7 +1,7 @@
// primitive_types6.rs
// Use a tuple index to access the second element of `numbers`.
// You can put this right into the `println!` where the ??? is.
-// Scroll down for hints!
+// Execute `rustlings hint primitive_types6` for hints!
// I AM NOT DONE
@@ -9,39 +9,3 @@ fn main() {
let numbers = (1, 2, 3);
println!("The second number is {}", ???);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// While you could use a destructuring `let` for the tuple here, try
-// indexing into it instead, as explained in the last example of the
-// Data Types -> The Tuple Type section of the book:
-// https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
-// Now you have another tool in your toolbox!
diff --git a/exercises/standard_library_types/arc1.rs b/exercises/standard_library_types/arc1.rs
index effd28a..04c169f 100644
--- a/exercises/standard_library_types/arc1.rs
+++ b/exercises/standard_library_types/arc1.rs
@@ -2,7 +2,7 @@
// Make this code compile by filling in a value for `shared_numbers` where the
// TODO comment is and creating an initial binding for `child_numbers`
// somewhere. Try not to create any copies of the `numbers` Vec!
-// Scroll down for hints :)
+// Execute `rustlings help arc1` for hints :)
// I AM NOT DONE
@@ -29,29 +29,3 @@ fn main() {
handle.join().unwrap();
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// 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.
diff --git a/exercises/standard_library_types/iterators2.rs b/exercises/standard_library_types/iterators2.rs
index ea523e7..a1274a2 100644
--- a/exercises/standard_library_types/iterators2.rs
+++ b/exercises/standard_library_types/iterators2.rs
@@ -3,7 +3,7 @@
// Step 1. Complete the `capitalize_first` function to pass the first two cases
// Step 2. Apply the `capitalize_first` function to a vector of strings, ensuring that it returns a vector of strings as well
// Step 3. Apply the `capitalize_first` function again to a list, but try and ensure it returns a single string
-// As always, there are hints below!
+// As always, there are hints if you execute `rustlings hint iterators2`!
// I AM NOT DONE
@@ -46,102 +46,3 @@ mod tests {
assert_eq!(capitalized_words, "Hello World");
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Step 1
-// You need to call something on `first` before it can be collected
-// Currently its type is `char`. Have a look at the methods that are available on that type:
-// https://doc.rust-lang.org/std/primitive.char.html
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Step 2
-// First you'll need to turn the Vec into an iterator
-// Then you'll need to apply your function unto each item in the vector
-// P.s. Don't forget to collect() at the end!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Step 3.
-// This is very similar to the previous test. The only real change is that you will need to
-// alter the type that collect is coerced into. For a bonus you could try doing this with a
-// turbofish
diff --git a/exercises/standard_library_types/iterators3.rs b/exercises/standard_library_types/iterators3.rs
index 8fc57f2..353cea6 100644
--- a/exercises/standard_library_types/iterators3.rs
+++ b/exercises/standard_library_types/iterators3.rs
@@ -4,8 +4,7 @@
// 1. Complete the divide function to get the first four tests to pass
// 2. Uncomment the last two tests and get them to pass by filling in
// values for `x` using `division_results`.
-// Scroll down for a minor hint for part 2, and scroll down further for
-// a major hint.
+// Execute `rustlings hint iterators3` to get some hints!
// Have fun :-)
// I AM NOT DONE
@@ -77,72 +76,3 @@ mod tests {
}
*/
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Minor hint: In each of the two cases in the match in main, you can create x with either
-// a 'turbofish' or by hinting the type of x to the compiler. You may try both.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Major hint: Have a look at the Iter trait and at the explanation of its collect function.
-// Especially the part about Result is interesting.
diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/standard_library_types/iterators4.rs
index 39be8bf..b945613 100644
--- a/exercises/standard_library_types/iterators4.rs
+++ b/exercises/standard_library_types/iterators4.rs
@@ -11,7 +11,7 @@ pub fn factorial(num: u64) -> u64 {
// - additional variables
// For the most fun don't use:
// - recursion
- // Scroll down for hints.
+ // Execute `rustlings hint iterators4` for hints.
}
#[cfg(test)]
@@ -32,32 +32,3 @@ mod tests {
assert_eq!(24, factorial(4));
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// In an imperative language you might write a for loop to iterate through
-// multiply the values into a mutable variable. Or you might write code more
-// functionally with recursion and a match clause. But you can also use ranges
-// and iterators to solve this in rust.
diff --git a/exercises/strings/strings1.rs b/exercises/strings/strings1.rs
index 3335734..8090244 100644
--- a/exercises/strings/strings1.rs
+++ b/exercises/strings/strings1.rs
@@ -1,5 +1,6 @@
// strings1.rs
-// Make me compile without changing the function signature! Scroll down for hints :)
+// Make me compile without changing the function signature!
+// Execute `rustlings hint strings1` for hints ;)
// I AM NOT DONE
@@ -11,38 +12,3 @@ fn main() {
fn current_favorite_color() -> String {
"blue"
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// The `current_favorite_color` function is currently returning a string slice with the `'static`
-// lifetime. We know this because the data of the string lives in our code itself -- it doesn't
-// come from a file or user input or another program -- so it will live as long as our program
-// lives. But it is still a string slice. There's one way to create a `String` by converting a
-// string slice covered in the Strings chapter of the book, and another way that uses the `From`
-// trait.
diff --git a/exercises/strings/strings2.rs b/exercises/strings/strings2.rs
index 3890cfe..5a2ce74 100644
--- a/exercises/strings/strings2.rs
+++ b/exercises/strings/strings2.rs
@@ -1,5 +1,6 @@
// strings2.rs
-// Make me compile without changing the function signature! Scroll down for hints :)
+// Make me compile without changing the function signature!
+// Execute `rustlings hint strings2` for hints :)
// I AM NOT DONE
@@ -15,32 +16,3 @@ fn main() {
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Yes, it would be really easy to fix this by just changing the value bound to `word` to be a
-// string slice instead of a `String`, wouldn't it?? There is a way to add one character to line
-// 6, though, that will coerce the `String` into a string slice.
diff --git a/exercises/tests/tests1.rs b/exercises/tests/tests1.rs
index 1465e37..b37cefa 100644
--- a/exercises/tests/tests1.rs
+++ b/exercises/tests/tests1.rs
@@ -4,7 +4,7 @@
// rustlings run --test exercises/tests/tests1.rs
// This test has a problem with it -- make the test compile! Make the test
-// pass! Make the test fail! Scroll down for hints :)
+// pass! Make the test fail! Execute `rustlings hint tests1` for hints :)
// I AM NOT DONE
@@ -15,37 +15,3 @@ mod tests {
assert!();
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// You don't even need to write any code to test -- you can just test values and run that, even
-// though you wouldn't do that in real life :) `assert!` is a macro that needs an argument.
-// Depending on the value of the argument, `assert!` will do nothing (in which case the test will
-// pass) or `assert!` will panic (in which case the test will fail). So try giving different values
-// to `assert!` and see which ones compile, which ones pass, and which ones fail :)
diff --git a/exercises/tests/tests2.rs b/exercises/tests/tests2.rs
index 81e30e0..0d981ad 100644
--- a/exercises/tests/tests2.rs
+++ b/exercises/tests/tests2.rs
@@ -1,6 +1,6 @@
// tests2.rs
// This test has a problem with it -- make the test compile! Make the test
-// pass! Make the test fail! Scroll down for hints :)
+// pass! Make the test fail! Execute `rustlings hint tests2` for hints :)
// I AM NOT DONE
@@ -11,36 +11,3 @@ mod tests {
assert_eq!();
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Like the previous exercise, you don't need to write any code to get this test to compile and
-// run. `assert_eq!` is a macro that takes two arguments and compares them. Try giving it two
-// values that are equal! Try giving it two arguments that are different! Try giving it two values
-// that are of different types! Try switching which argument comes first and which comes second!
diff --git a/exercises/tests/tests3.rs b/exercises/tests/tests3.rs
index af48095..693b8aa 100644
--- a/exercises/tests/tests3.rs
+++ b/exercises/tests/tests3.rs
@@ -1,7 +1,8 @@
// tests3.rs
// This test isn't testing our function -- make it do that in such a way that
// the test passes. Then write a second test that tests whether we get the result
-// we expect to get when we call `is_even(5)`. Scroll down for hints!
+// we expect to get when we call `is_even(5)`.
+// Execute `rustlings hint tests3` for hints :)
// I AM NOT DONE
@@ -18,28 +19,3 @@ mod tests {
assert!();
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// You can call a function right where you're passing arguments to `assert!` -- so you could do
-// something like `assert!(having_fun())`. If you want to check that you indeed get false, you
-// can negate the result of what you're doing using `!`, like `assert!(!having_fun())`.
diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs
index d23553e..288ddd1 100644
--- a/exercises/threads/threads1.rs
+++ b/exercises/threads/threads1.rs
@@ -1,8 +1,8 @@
// threads1.rs
-// Make this compile! Scroll down for hints :) The idea is the thread
-// spawned on line 19 is completing jobs while the main thread is
+// Make this compile! Execute `rustlings hint threads1` for hints :)
+// The idea is the thread spawned on line 19 is completing jobs while the main thread is
// monitoring progress until 10 jobs are completed. If you see 6 lines
-// of "waiting..." and the program ends without timing out the playground,
+// of "waiting..." and the program ends without timing out when running,
// you've got it :)
// I AM NOT DONE
@@ -29,69 +29,3 @@ fn main() {
thread::sleep(Duration::from_millis(500));
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// `Arc` is an Atomic Reference Counted pointer that allows safe, shared access
-// to **immutable** data. But we want to *change* the number of `jobs_completed`
-// so we'll need to also use another type that will only allow one thread to
-// mutate the data at a time. Take a look at this section of the book:
-// https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct
-// and keep scrolling if you'd like more hints :)
-
-
-
-
-
-
-
-
-
-
-// Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like:
-// `let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));`
-// Similar to the code in the example in the book that happens after the text
-// that says "We can use Arc<T> to fix this.". If not, give that a try! If you
-// do and would like more hints, keep scrolling!!
-
-
-
-
-
-
-
-
-
-
-
-
-// Make sure neither of your threads are holding onto the lock of the mutex
-// while they are sleeping, since this will prevent the other thread from
-// being allowed to get the lock. Locks are automatically released when
-// they go out of scope.
-
-// Ok, so, real talk, this was actually tricky for *me* to do too. And
-// I could see a lot of different problems you might run into, so at this
-// point I'm not sure which one you've hit :) Please see a few possible
-// answers on https://github.com/carols10cents/rustlings/issues/3 --
-// mine is a little more complicated because I decided I wanted to see
-// the number of jobs currently done when I was checking the status.
-
-// Please open an issue if you're still running into a problem that
-// these hints are not helping you with, or if you've looked at the sample
-// answers and don't understand why they work and yours doesn't.
-
-// If you've learned from the sample solutions, I encourage you to come
-// back to this exercise and try it again in a few days to reinforce
-// what you've learned :)
diff --git a/exercises/variables/variables1.rs b/exercises/variables/variables1.rs
index 174ad80..5ddc37d 100644
--- a/exercises/variables/variables1.rs
+++ b/exercises/variables/variables1.rs
@@ -1,5 +1,5 @@
// variables1.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute the command `rustlings hint variables1` if you want a hint :)
// About this `I AM NOT DONE` thing:
// We sometimes encourage you to keep trying things on a given exercise,
@@ -12,38 +12,3 @@ fn main() {
x = 5;
println!("x has the value {}", x);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Hint: The declaration on line 5 is missing a keyword that is needed in Rust
-// to create a new variable binding.
diff --git a/exercises/variables/variables2.rs b/exercises/variables/variables2.rs
index e3c3b76..7774a8f 100644
--- a/exercises/variables/variables2.rs
+++ b/exercises/variables/variables2.rs
@@ -1,5 +1,5 @@
// variables2.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute the command `rustlings hint variables2` if you want a hint :)
// I AM NOT DONE
@@ -11,39 +11,3 @@ fn main() {
println!("Not ten!");
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// The compiler message is saying that Rust cannot infer the type that the
-// variable binding `x` has with what is given here.
-// What happens if you annotate line 5 with a type annotation?
-// What if you give x a value?
-// What if you do both?
-// What type should x be, anyway?
-// What if x is the same type as 10? What if it's a different type?
diff --git a/exercises/variables/variables3.rs b/exercises/variables/variables3.rs
index 7e3fd93..07b1a52 100644
--- a/exercises/variables/variables3.rs
+++ b/exercises/variables/variables3.rs
@@ -1,5 +1,5 @@
// variables3.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute the command `rustlings hint variables3` if you want a hint :)
// I AM NOT DONE
@@ -9,37 +9,3 @@ fn main() {
x = 5;
println!("Number {}", x);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// In Rust, variable bindings are immutable by default. But here we're trying
-// to reassign a different value to x! There's a keyword we can use to make
-// a variable binding mutable instead.
diff --git a/exercises/variables/variables4.rs b/exercises/variables/variables4.rs
index 33eca9e..77f1e9a 100644
--- a/exercises/variables/variables4.rs
+++ b/exercises/variables/variables4.rs
@@ -1,5 +1,5 @@
// variables4.rs
-// Make me compile! Scroll down for hints :)
+// Make me compile! Execute the command `rustlings hint variables4` if you want a hint :)
// I AM NOT DONE
@@ -7,41 +7,3 @@ fn main() {
let x: i32;
println!("Number {}", x);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Oops! In this exercise, we have a variable binding that we've created on
-// line 5, and we're trying to use it on line 6, but we haven't given it a
-// value. We can't print out something that isn't there; try giving x a value!
-// This is an error that can cause bugs that's very easy to make in any
-// programming language -- thankfully the Rust compiler has caught this for us!
diff --git a/info.toml b/info.toml
index d908c9e..84d5821 100644
--- a/info.toml
+++ b/info.toml
@@ -1,241 +1,612 @@
# VARIABLES
[[exercises]]
+name = "variables1"
path = "exercises/variables/variables1.rs"
mode = "compile"
+hint = """
+Hint: The declaration on line 5 is missing a keyword that is needed in Rust
+to create a new variable binding."""
[[exercises]]
+name = "variables2"
path = "exercises/variables/variables2.rs"
mode = "compile"
+hint = """
+The compiler message is saying that Rust cannot infer the type that the
+variable binding `x` has with what is given here.
+What happens if you annotate line 5 with a type annotation?
+What if you give x a value?
+What if you do both?
+What type should x be, anyway?
+What if x is the same type as 10? What if it's a different type?"""
[[exercises]]
+name = "variables3"
path = "exercises/variables/variables3.rs"
mode = "compile"
+hint = """
+In Rust, variable bindings are immutable by default. But here we're trying
+to reassign a different value to x! There's a keyword we can use to make
+a variable binding mutable instead."""
[[exercises]]
+name = "variables4"
path = "exercises/variables/variables4.rs"
mode = "compile"
+hint = """
+Oops! In this exercise, we have a variable binding that we've created on
+line 5, and we're trying to use it on line 6, but we haven't given it a
+value. We can't print out something that isn't there; try giving x a value!
+This is an error that can cause bugs that's very easy to make in any
+programming language -- thankfully the Rust compiler has caught this for us!"""
# IF
[[exercises]]
+name = "if1"
path = "exercises/if/if1.rs"
mode = "test"
+hint = """
+It's possible to do this in one line if you would like!
+Some similar examples from other languages:
+- In C(++) this would be: `a > b ? a : b`
+- In Python this would be: `a if a > b else b`
+Remember in Rust that:
+- the `if` condition does not need to be surrounded by parentheses
+- `if`/`else` conditionals are expressions
+- Each condition is followed by a `{}` block."""
# FUNCTIONS
[[exercises]]
+name = "functions1"
path = "exercises/functions/functions1.rs"
mode = "compile"
+hint = """
+This main function is calling a function that it expects to exist, but the
+function doesn't exist. It expects this function to have the name `call_me`.
+It expects this function to not take any arguments and not return a value.
+Sounds a lot like `main`, doesn't it?"""
[[exercises]]
+name = "functions2"
path = "exercises/functions/functions2.rs"
mode = "compile"
+hint = """
+Rust requires that all parts of a function's signature have type annotations,
+but `call_me` is missing the type annotation of `num`."""
[[exercises]]
+name = "functions3"
path = "exercises/functions/functions3.rs"
mode = "compile"
+hint = """
+This time, the function *declaration* is okay, but there's something wrong
+with the place where we're calling the function."""
[[exercises]]
+name = "functions4"
path = "exercises/functions/functions4.rs"
mode = "compile"
+hint = """
+The error message points to line 12 and says it expects a type after the
+`->`. This is where the function's return type should be-- take a look at
+the `is_even` function for an example!"""
[[exercises]]
+name = "functions5"
path = "exercises/functions/functions5.rs"
mode = "compile"
+hint = """
+This is a really common error that can be fixed by removing one character.
+It happens because Rust distinguishes between expressions and statements: expressions return
+a value based on its operand, and statements simply return a () type which behaves just like `void` in C/C++ language.
+We want to return a value of `i32` type from the `square` function, but it is returning a `()` type...
+They are not the same. There are two solutions:
+1. Add a `return` ahead of `num * num;`
+2. remove `;`, make it to be `num * num`"""
# TEST 1
[[exercises]]
+name = "test1"
path = "exercises/test1.rs"
mode = "test"
+hint = "No hints this time ;)"
# PRIMITIVE TYPES
[[exercises]]
+name = "primitive_types1"
path = "exercises/primitive_types/primitive_types1.rs"
mode = "compile"
+hint = "No hints this time ;)"
[[exercises]]
+name = "primitive_types2"
path = "exercises/primitive_types/primitive_types2.rs"
mode = "compile"
+hint = "No hints this time ;)"
[[exercises]]
+name = "primitive_types3"
path = "exercises/primitive_types/primitive_types3.rs"
mode = "compile"
+hint = """
+There's a shorthand to initialize Arrays with a certain size that does not
+require you to type in 100 items (but you certainly can if you want!).
+For example, you can do:
+let array = ["Are we there yet?"; 10];
+
+Bonus: what are some other things you could have that would return true
+for `a.len() >= 100`?"""
[[exercises]]
+name = "primitive_types4"
path = "exercises/primitive_types/primitive_types4.rs"
mode = "test"
+hint = """
+Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book:
+https://doc.rust-lang.org/book/ch04-03-slices.html
+and use the starting and ending indices of the items in the Array
+that you want to end up in the slice.
+
+If you're curious why the right hand of the `==` comparison does not
+have an ampersand for a reference since the left hand side is a
+reference, take a look at the Deref coercions section of the book:
+https://doc.rust-lang.org/book/ch15-02-deref.html"""
[[exercises]]
+name = "primitive_types5"
path = "exercises/primitive_types/primitive_types5.rs"
mode = "compile"
+hint = """
+Take a look at the Data Types -> The Tuple Type section of the book:
+https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
+Particularly the part about destructuring (second to last example in the section).
+You'll need to make a pattern to bind `name` and `age` to the appropriate parts
+of the tuple. You can do it!!"""
[[exercises]]
+name = "primitive_types6"
path = "exercises/primitive_types/primitive_types6.rs"
mode = "compile"
+hint = """
+While you could use a destructuring `let` for the tuple here, try
+indexing into it instead, as explained in the last example of the
+Data Types -> The Tuple Type section of the book:
+https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
+Now you have another tool in your toolbox!"""
# STRUCTS
[[exercises]]
+name = "structs1"
path = "exercises/structs/structs1.rs"
mode = "test"
+hint = "No hints this time ;)"
[[exercises]]
+name = "structs2"
path = "exercises/structs/structs2.rs"
mode = "test"
+hint = "No hints this time ;)"
# STRINGS
[[exercises]]
+name = "strings1"
path = "exercises/strings/strings1.rs"
mode = "compile"
+hint = """
+The `current_favorite_color` function is currently returning a string slice with the `'static`
+lifetime. We know this because the data of the string lives in our code itself -- it doesn't
+come from a file or user input or another program -- so it will live as long as our program
+lives. But it is still a string slice. There's one way to create a `String` by converting a
+string slice covered in the Strings chapter of the book, and another way that uses the `From`
+trait."""
[[exercises]]
+name = "strings2"
path = "exercises/strings/strings2.rs"
mode = "compile"
+hint = """
+Yes, it would be really easy to fix this by just changing the value bound to `word` to be a
+string slice instead of a `String`, wouldn't it?? There is a way to add one character to line
+6, though, that will coerce the `String` into a string slice."""
# TEST 2
[[exercises]]
+name = "test2"
path = "exercises/test2.rs"
mode = "compile"
+hint = "No hints this time ;)"
# ENUMS
[[exercises]]
+name = "enums1"
path = "exercises/enums/enums1.rs"
mode = "compile"
+hint = """
+Hint: The declaration of the enumeration type has not been defined yet."""
[[exercises]]
+name = "enums2"
path = "exercises/enums/enums2.rs"
mode = "compile"
+hint = """
+Hint: you can create enumerations that have different variants with different types
+such as no data, anonymous structs, a single string, tuples, ...etc"""
[[exercises]]
+name = "enums3"
path = "exercises/enums/enums3.rs"
mode = "test"
+hint = "No hints this time ;)"
# TESTS
[[exercises]]
+name = "tests1"
path = "exercises/tests/tests1.rs"
mode = "test"
+hint = """
+You don't even need to write any code to test -- you can just test values and run that, even
+though you wouldn't do that in real life :) `assert!` is a macro that needs an argument.
+Depending on the value of the argument, `assert!` will do nothing (in which case the test will
+pass) or `assert!` will panic (in which case the test will fail). So try giving different values
+to `assert!` and see which ones compile, which ones pass, and which ones fail :)"""
[[exercises]]
+name = "tests2"
path = "exercises/tests/tests2.rs"
mode = "test"
+hint = """
+Like the previous exercise, you don't need to write any code to get this test to compile and
+run. `assert_eq!` is a macro that takes two arguments and compares them. Try giving it two
+values that are equal! Try giving it two arguments that are different! Try giving it two values
+that are of different types! Try switching which argument comes first and which comes second!"""
[[exercises]]
+name = "tests3"
path = "exercises/tests/tests3.rs"
mode = "test"
+hint = """
+You can call a function right where you're passing arguments to `assert!` -- so you could do
+something like `assert!(having_fun())`. If you want to check that you indeed get false, you
+can negate the result of what you're doing using `!`, like `assert!(!having_fun())`."""
# TEST 3
[[exercises]]
+name = "test3"
path = "exercises/test3.rs"
mode = "test"
+hint = "No hints this time ;)"
# MODULES
[[exercises]]
+name = "modules1"
path = "exercises/modules/modules1.rs"
mode = "compile"
+hint = """
+Everything is private in Rust by default-- but there's a keyword we can use
+to make something public! The compiler error should point to the thing that
+needs to be public."""
[[exercises]]
+name = "modules2"
path = "exercises/modules/modules2.rs"
mode = "compile"
+hint = """
+The delicious_snacks module is trying to present an external
+interface (the `fruit` and `veggie` constants) that is different than
+its internal structure (the `fruits` and `veggies` modules and
+associated constants). It's almost there except for one keyword missing for
+each constant."""
# MACROS
[[exercises]]
+name = "macros1"
path = "exercises/macros/macros1.rs"
mode = "compile"
+hint = """
+When you call a macro, you need to add something special compared to a
+regular function call. If you're stuck, take a look at what's inside
+`my_macro`."""
[[exercises]]
+name = "macros2"
path = "exercises/macros/macros2.rs"
mode = "compile"
+hint = """
+Macros don't quite play by the same rules as the rest of Rust, in terms of
+what's available where.
+
+Unlike other things in Rust, the order of "where you define a macro" versus
+"where you use it" actually matters."""
[[exercises]]
+name = "macros3"
path = "exercises/macros/macros3.rs"
mode = "compile"
+hint = """
+In order to use a macro outside of its module, you need to do something
+special to the module to lift the macro out into its parent.
+
+The same trick also works on "extern crate" statements for crates that have
+exported macros, if you've seen any of those around."""
[[exercises]]
+name = "macros4"
path = "exercises/macros/macros4.rs"
mode = "compile"
-
+hint = """
+You only need to add a single character to make this compile.
+The way macros are written, it wants to see something between each
+"macro arm", so it can separate them."""
# TEST 4
[[exercises]]
+name = "test4"
path = "exercises/test4.rs"
mode = "compile"
+hint = "No hints this time ;)"
# MOVE SEMANTICS
[[exercises]]
+name = "move_semantics1"
path = "exercises/move_semantics/move_semantics1.rs"
mode = "compile"
+hint = """
+So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 11,
+right? The fix for this is going to be adding one keyword, and the addition is NOT on line 11
+where the error is."""
[[exercises]]
+name = "move_semantics2"
path = "exercises/move_semantics/move_semantics2.rs"
mode = "compile"
-
-[[exercises]]
+hint = """
+So `vec0` is being *moved* into the function `fill_vec` when we call it on
+line 7, which means it gets dropped at the end of `fill_vec`, which means we
+can't use `vec0` again on line 10 (or anywhere else in `main` after the
+`fill_vec` call for that matter). We could fix this in a few ways, try them
+all!
+1. Make another, separate version of the data that's in `vec0` and pass that
+ to `fill_vec` instead.
+2. Make `fill_vec` borrow its argument instead of taking ownership of it,
+ and then copy the data within the function in order to return an owned
+ `Vec<i32>`
+3. Make `fill_vec` *mutably* borrow its argument (which will need to be
+ mutable), modify it directly, then not return anything. Then you can get rid
+ of `vec1` entirely -- note that this will change what gets printed by the
+ first `println!`"""
+
+[[exercises]]
+name = "move_semantics3"
path = "exercises/move_semantics/move_semantics3.rs"
mode = "compile"
+hint = """
+The difference between this one and the previous ones is that the first line
+of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can,
+instead of adding that line back, add `mut` in one place that will change
+an existing binding to be a mutable binding instead of an immutable one :)"""
[[exercises]]
+name = "move_semantics4"
path = "exercises/move_semantics/move_semantics4.rs"
mode = "compile"
+hint = """
+Stop reading whenever you feel like you have enough direction :) Or try
+doing one step and then fixing the compiler errors that result!
+So the end goal is to:
+ - get rid of the first line in main that creates the new vector
+ - so then `vec0` doesn't exist, so we can't pass it to `fill_vec`
+ - we don't want to pass anything to `fill_vec`, so its signature should
+ reflect that it does not take any arguments
+ - since we're not creating a new vec in `main` anymore, we need to create
+ a new vec in `fill_vec`, similarly to the way we did in `main`"""
# ERROR HANDLING
[[exercises]]
+name = "errors1"
path = "exercises/error_handling/errors1.rs"
mode = "test"
-
-[[exercises]]
+hint = """
+`Err` is one of the variants of `Result`, so what the 2nd test is saying
+is that `generate_nametag_text` should return a `Result` instead of an
+`Option`.
+
+To make this change, you'll need to:
+ - update the return type in the function signature to be a Result<String, String> that
+ could be the variants `Ok(String)` and `Err(String)`
+ - change the body of the function to return `Ok(stuff)` where it currently
+ returns `Some(stuff)`
+ - change the body of the function to return `Err(error message)` where it
+ currently returns `None`
+ - change the first test to expect `Ok(stuff)` where it currently expects
+ `Some(stuff)`."""
+
+[[exercises]]
+name = "errors2"
path = "exercises/error_handling/errors2.rs"
mode = "test"
+hint = """
+One way to handle this is using a `match` statement on
+`item_quantity.parse::<i32>()` where the cases are `Ok(something)` and
+`Err(something)`. This pattern is very common in Rust, though, so there's
+a `?` operator that does pretty much what you would make that match statement
+do for you! Take a look at this section of the Error Handling chapter:
+https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
+and give it a try!"""
[[exercises]]
+name = "errors3"
path = "exercises/error_handling/errors3.rs"
mode = "test"
+hint = """
+If other functions can return a `Result`, why shouldn't `main`?"""
[[exercises]]
+name = "errors4"
path = "exercises/error_handling/errorsn.rs"
mode = "test"
+hint = """
+First hint: To figure out what type should go where the ??? is, take a look
+at the test helper function `test_with_str`, since it returns whatever
+`read_and_validate` returns and`test_with_str` has its signature fully
+specified.
+
+
+Next hint: There are three places in `read_and_validate` that we call a
+function that returns a `Result` (that is, the functions might fail).
+Apply the `?` operator on those calls so that we return immediately from
+`read_and_validate` if those function calls fail.
+
+
+Another hint: under the hood, the `?` operator calls `From::from`
+on the error value to convert it to a boxed trait object, a Box<dyn error::Error>,
+which is polymorphic-- that means that lots of different kinds of errors
+can be returned from the same function because all errors act the same
+since they all implement the `error::Error` trait.
+Check out this section of the book:
+https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
+
+
+Another another hint: Note that because the `?` operator returns
+the *unwrapped* value in the `Ok` case, if we want to return a `Result` from
+`read_and_validate` for *its* success case, we'll have to rewrap a value
+that we got from the return value of a `?`ed call in an `Ok`-- this will
+look like `Ok(something)`.
+
+
+Another another another hint: `Result`s must be "used", that is, you'll
+get a warning if you don't handle a `Result` that you get in your
+function. Read more about that in the `std::result` module docs:
+https://doc.rust-lang.org/std/result/#results-must-be-used"""
# OPTIONS / RESULTS
[[exercises]]
+name = "option1"
path = "exercises/error_handling/option1.rs"
mode = "test"
+hint = """
+Try using a `match` statement where the arms are `Some(thing)` and `None`.
+Or set a default value to print out if you get `None` by using the
+function `unwrap_or`.
+Or use an `if let` statement on the result of `pop()` to both destructure
+a `Some` value and only print out something if we have a value!"""
[[exercises]]
+name = "option2"
path = "exercises/error_handling/result1.rs"
mode = "test"
+hint = """
+`PositiveNonzeroInteger::new` is always creating a new instance and returning an `Ok` result.
+It should be doing some checking, returning an `Err` result if those checks fail, and only
+returning an `Ok` result if those checks determine that everything is... okay :)"""
# STANDARD LIBRARY 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."""
[[exercises]]
+name = "iterators2"
path = "exercises/standard_library_types/iterators2.rs"
mode = "test"
+hint = """
+Step 1
+You need to call something on `first` before it can be collected
+Currently its type is `char`. Have a look at the methods that are available on that type:
+https://doc.rust-lang.org/std/primitive.char.html
+
+
+Step 2
+First you'll need to turn the Vec into an iterator
+Then you'll need to apply your function unto each item in the vector
+P.s. Don't forget to collect() at the end!
+
+
+Step 3.
+This is very similar to the previous test. The only real change is that you will need to
+alter the type that collect is coerced into. For a bonus you could try doing this with a
+turbofish"""
[[exercises]]
+name = "iterators3"
path = "exercises/standard_library_types/iterators3.rs"
mode = "test"
+hint = """
+Minor hint: In each of the two cases in the match in main, you can create x with either
+a 'turbofish' or by hinting the type of x to the compiler. You may try both.
+
+Major hint: Have a look at the Iter trait and at the explanation of its collect function.
+Especially the part about Result is interesting."""
[[exercises]]
+name = "iterators4"
path = "exercises/standard_library_types/iterators4.rs"
mode = "test"
+hint = """
+In an imperative language you might write a for loop to iterate through
+multiply the values into a mutable variable. Or you might write code more
+functionally with recursion and a match clause. But you can also use ranges
+and iterators to solve this in rust."""
# THREADS
[[exercises]]
+name = "threads1"
path = "exercises/threads/threads1.rs"
mode = "compile"
+hint = """
+`Arc` is an Atomic Reference Counted pointer that allows safe, shared access
+to **immutable** data. But we want to *change* the number of `jobs_completed`
+so we'll need to also use another type that will only allow one thread to
+mutate the data at a time. Take a look at this section of the book:
+https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct
+and keep reading if you'd like more hints :)
+
+
+Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like:
+`let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));`
+Similar to the code in the example in the book that happens after the text
+that says "We can use Arc<T> to fix this.". If not, give that a try! If you
+do and would like more hints, keep reading!!
+
+
+Make sure neither of your threads are holding onto the lock of the mutex
+while they are sleeping, since this will prevent the other thread from
+being allowed to get the lock. Locks are automatically released when
+they go out of scope.
+
+Ok, so, real talk, this was actually tricky for *me* to do too. And
+I could see a lot of different problems you might run into, so at this
+point I'm not sure which one you've hit :)
+
+Please open an issue if you're still running into a problem that
+these hints are not helping you with, or if you've looked at the sample
+answers and don't understand why they work and yours doesn't.
+
+If you've learned from the sample solutions, I encourage you to come
+back to this exercise and try it again in a few days to reinforce
+what you've learned :)"""
diff --git a/src/exercise.rs b/src/exercise.rs
index f27b545..be59284 100644
--- a/src/exercise.rs
+++ b/src/exercise.rs
@@ -28,8 +28,10 @@ pub struct ExerciseList {
#[derive(Deserialize)]
pub struct Exercise {
+ pub name: String,
pub path: PathBuf,
pub mode: Mode,
+ pub hint: String,
}
#[derive(PartialEq, Debug)]
@@ -128,8 +130,10 @@ mod test {
fn test_clean() {
File::create(&temp_file()).unwrap();
let exercise = Exercise {
+ name: String::from("example"),
path: PathBuf::from("example.rs"),
mode: Mode::Test,
+ hint: String::from(""),
};
exercise.clean();
assert!(!Path::new(&temp_file()).exists());
diff --git a/src/main.rs b/src/main.rs
index e42dff4..5a4af53 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -25,8 +25,13 @@ fn main() {
SubCommand::with_name("run")
.alias("r")
.about("Runs/Tests a single exercise")
- .arg(Arg::with_name("file").required(true).index(1))
- .arg(Arg::with_name("test").short("t").long("test").help("Run the file as a test")),
+ .arg(Arg::with_name("name").required(true).index(1)),
+ )
+ .subcommand(
+ SubCommand::with_name("hint")
+ .alias("h")
+ .about("Returns a hint for the current exercise")
+ .arg(Arg::with_name("name").required(true).index(1)),
)
.get_matches();
@@ -55,26 +60,38 @@ fn main() {
let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises;
if let Some(ref matches) = matches.subcommand_matches("run") {
- let filename = matches.value_of("file").unwrap_or_else(|| {
- println!("Please supply a file name!");
+ let name = matches.value_of("name").unwrap_or_else(|| {
+ println!("Please supply an exercise name!");
std::process::exit(1);
});
- let matching_exercise = |e: &&Exercise| {
- Path::new(filename)
- .canonicalize()
- .map(|p| p.ends_with(&e.path))
- .unwrap_or(false)
- };
+ let matching_exercise = |e: &&Exercise| name == e.name;
let exercise = exercises.iter().find(matching_exercise).unwrap_or_else(|| {
- println!("No exercise found for your file name!");
+ println!("No exercise found for your given name!");
std::process::exit(1)
});
run(&exercise).unwrap_or_else(|_| std::process::exit(1));
}
+ if let Some(ref matches) = matches.subcommand_matches("hint") {
+ let name = matches.value_of("name").unwrap_or_else(|| {
+ println!("Please supply an exercise name!");
+ std::process::exit(1);
+ });
+
+ let exercise = exercises
+ .iter()
+ .find(|e| name == e.name)
+ .unwrap_or_else(|| {
+ println!("No exercise found for your given name!");
+ std::process::exit(1)
+ });
+
+ println!("{}", exercise.hint);
+ }
+
if matches.subcommand_matches("verify").is_some() {
verify(&exercises).unwrap_or_else(|_| std::process::exit(1));
}
diff --git a/tests/fixture/failure/info.toml b/tests/fixture/failure/info.toml
index f4e7c0c..e5949f9 100644
--- a/tests/fixture/failure/info.toml
+++ b/tests/fixture/failure/info.toml
@@ -1,7 +1,11 @@
[[exercises]]
+name = "compFailure"
path = "compFailure.rs"
mode = "compile"
+hint = ""
[[exercises]]
+name = "testFailure"
path = "testFailure.rs"
-mode = "test" \ No newline at end of file
+mode = "test"
+hint = "Hello!"
diff --git a/tests/fixture/success/info.toml b/tests/fixture/success/info.toml
index e255db9..68d3538 100644
--- a/tests/fixture/success/info.toml
+++ b/tests/fixture/success/info.toml
@@ -1,7 +1,11 @@
[[exercises]]
+name = "compSuccess"
path = "compSuccess.rs"
mode = "compile"
+hint = """"""
[[exercises]]
+name = "testSuccess"
path = "testSuccess.rs"
-mode = "test" \ No newline at end of file
+mode = "test"
+hint = """"""
diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs
index 897cd2a..32f4341 100644
--- a/tests/integration_tests.rs
+++ b/tests/integration_tests.rs
@@ -43,7 +43,7 @@ fn verify_all_failure() {
fn run_single_compile_success() {
Command::cargo_bin("rustlings")
.unwrap()
- .args(&["r", "compSuccess.rs"])
+ .args(&["r", "compSuccess"])
.current_dir("tests/fixture/success/")
.assert()
.success();
@@ -53,7 +53,7 @@ fn run_single_compile_success() {
fn run_single_compile_failure() {
Command::cargo_bin("rustlings")
.unwrap()
- .args(&["r", "compFailure.rs"])
+ .args(&["r", "compFailure"])
.current_dir("tests/fixture/failure/")
.assert()
.code(1);
@@ -63,7 +63,7 @@ fn run_single_compile_failure() {
fn run_single_test_success() {
Command::cargo_bin("rustlings")
.unwrap()
- .args(&["r", "testSuccess.rs"])
+ .args(&["r", "testSuccess"])
.current_dir("tests/fixture/success/")
.assert()
.success();
@@ -73,7 +73,7 @@ fn run_single_test_success() {
fn run_single_test_failure() {
Command::cargo_bin("rustlings")
.unwrap()
- .args(&["r", "testFailure.rs"])
+ .args(&["r", "testFailure"])
.current_dir("tests/fixture/failure/")
.assert()
.code(1);
@@ -110,6 +110,16 @@ fn run_single_test_no_exercise() {
}
#[test]
+fn get_hint_for_single_test() {
+ Command::cargo_bin("rustlings")
+ .unwrap()
+ .args(&["h", "testFailure"])
+ .current_dir("tests/fixture/failure")
+ .assert()
+ .code(0)
+ .stdout("Hello!\n");
+
+#[test]
fn all_exercises_require_confirmation() {
for exercise in glob("exercises/**/*.rs").unwrap() {
let path = exercise.unwrap();