From 79ab030ac1b510a690d548028f365d6f53c65d42 Mon Sep 17 00:00:00 2001 From: parrrate Date: Thu, 9 Apr 2026 12:56:14 +0000 Subject: [PATCH] rcchars --- book.toml | 3 +++ src/SUMMARY.md | 3 +++ src/chapter_2.md | 1 + src/exercises/anystr.md | 3 +++ src/exercises/bool_stream.md | 23 +++++++++++++++++ src/exercises/rcchars.md | 50 ++++++++++++++++++++++++++++++++++++ src/exercises/refbind.md | 2 +- src/overview.md | 4 ++- 8 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/chapter_2.md create mode 100644 src/exercises/anystr.md create mode 100644 src/exercises/rcchars.md diff --git a/book.toml b/book.toml index c0b5810..8c6b8f8 100644 --- a/book.toml +++ b/book.toml @@ -5,6 +5,9 @@ multilingual = false src = "src" title = "Exercises" +[rust] +edition = "2021" + [build] build-dir = "book" create-missing = false diff --git a/src/SUMMARY.md b/src/SUMMARY.md index d20b606..8c73d37 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -7,3 +7,6 @@ - [test1.rs (refbind)](./exercises/refbind.md) - [A/A1/A2](./exercises/multiple_blanket.md) - [BoolStream](./exercises/bool_stream.md) + - [RcChars](./exercises/rcchars.md) +- [Chapter 2](./chapter_2.md) + - [AnyStr](./exercises/anystr.md) diff --git a/src/chapter_2.md b/src/chapter_2.md new file mode 100644 index 0000000..7ebb596 --- /dev/null +++ b/src/chapter_2.md @@ -0,0 +1 @@ +# Chapter 2 diff --git a/src/exercises/anystr.md b/src/exercises/anystr.md new file mode 100644 index 0000000..2445608 --- /dev/null +++ b/src/exercises/anystr.md @@ -0,0 +1,3 @@ +Create something similar to [Python's `typing.AnyStr`]. + +[Python's `typing.AnyStr`]: https://docs.python.org/3/library/typing.html#typing.AnyStr diff --git a/src/exercises/bool_stream.md b/src/exercises/bool_stream.md index fa2990e..7988ab1 100644 --- a/src/exercises/bool_stream.md +++ b/src/exercises/bool_stream.md @@ -1,6 +1,29 @@ Make `test_covariance` compile by making `BoolStream<'a>` covariant `'a`. Restrictions: - Can only change implementation details of `BoolStream` and its methods and add extra items outside of what's given, i.e. no signature/test change. - Changed version must behave the same way. + +Consider the following code: +```rust,compile_fail +pub struct BoolStream<'a>( + Box (bool, BoolStream<'a>)>, +); + +impl<'a> BoolStream<'a> { + pub fn new(f: impl 'a + FnOnce() -> (bool, Self)) -> Self { + Self(Box::new(f)) + } + + pub fn next(self) -> (bool, Self) { + self.0() + } +} + +fn test_covariance<'a: 'b, 'b>(e: BoolStream<'a>) -> BoolStream<'b> { + e +} +``` +Why does it fail to compile? + ```rust pub struct BoolStream<'a>( // change this diff --git a/src/exercises/rcchars.md b/src/exercises/rcchars.md new file mode 100644 index 0000000..4f93c57 --- /dev/null +++ b/src/exercises/rcchars.md @@ -0,0 +1,50 @@ +[`Chars`] but keeping a strong reference ([`Rc`]) to the string. + +[`Chars`]: https://doc.rust-lang.org/std/str/struct.Chars.html +[`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html + +```rust +# mod rcchars { +# pub struct RcChars { _rc: std::rc::Rc, chars: std::mem::MaybeUninit> } +# impl Iterator for RcChars { +# type Item = char; +# fn next(&mut self) -> Option { unsafe { self.chars.assume_init_mut() }.next() } +# } +# impl RcChars { +# pub fn from_rc(rc: std::rc::Rc) -> Self { +# let mut new = Self { _rc: rc, chars: std::mem::MaybeUninit::uninit() }; +# new.chars .write(unsafe { &*std::rc::Rc::as_ptr(&new._rc) }.chars()); +# new +# } +# } +# impl From> for RcChars { +# fn from(value: std::rc::Rc) -> Self { Self::from_rc(value) } +# } +# impl Drop for RcChars { +# fn drop(&mut self) { unsafe { self.chars.assume_init_drop() } } +# } +# } +# use std::rc::Rc; +# use rcchars::RcChars; +{ + let rc = Rc::new("abc".to_string()); + let rcc = RcChars::from(rc.clone()); + drop(rc); + assert_eq!(rcc.collect::>(), ['a', 'b', 'c']); +} +{ + let rc = Rc::new("abc".to_string()); + let rcc = RcChars::from(rc); + let rcc = Box::new(rcc); + assert_eq!(rcc.collect::>(), ['a', 'b', 'c']); +} +``` + +## Solutions +- [Solution] used in rattlescript. +- [Same solution] but with some extra comments. +- [Another solution]. + +[Solution]: https://github.com/HavenSelph/rattlescript/blob/f8bafb8b063b9bf056efb1ea14188db0624d981c/src/interpreter/value.rs#L21-L50 +[Same solution]: https://gist.github.com/timotheyca/7e46c9734653b2fcbe826ea4d13b9aa0 +[Another solution]: https://gist.github.com/timotheyca/bc419e0997d6f7ea5722fd2823a78c62 diff --git a/src/exercises/refbind.md b/src/exercises/refbind.md index 232822d..078237f 100644 --- a/src/exercises/refbind.md +++ b/src/exercises/refbind.md @@ -7,7 +7,7 @@ fn refbind Option<&T>>(f: F, fa: Option<&T>) -> Option<&T> { } } # } -# fn refbind<'a,'b,T:'a+?Sized>(f:impl'a+Fn(&'a T)->Option<&'b T>,fa:Option<&'a T>)->Option<&'b T>{fa.and_then(f)} +# fn refbind<'a,'b,T:'a+?Sized>(f:impl 'a+Fn(&'a T)->Option<&'b T>,fa:Option<&'a T>)->Option<&'b T>{fa.and_then(f)} // don't change anything below diff --git a/src/overview.md b/src/overview.md index 45367e1..d5f27ae 100644 --- a/src/overview.md +++ b/src/overview.md @@ -2,9 +2,11 @@ Random Rust exercises. +**Warning: this is a live-edited website, errors and accidental spoilers are to be expected.** + # Solutions -Currently solutions are only provided in a non-human-readable form in the page source. +Currently solutions are mostly provided in a non-human-readable form in the page source. Those are mostly intended for testing that the exercise is even possible to solve. ```rust # /*