Skip to content

Commit

Permalink
Add old examples and consistently format authors
Browse files Browse the repository at this point in the history
  • Loading branch information
WaffleLapkin committed May 11, 2024
1 parent 7d811f2 commit 295a39d
Show file tree
Hide file tree
Showing 28 changed files with 552 additions and 91 deletions.
7 changes: 7 additions & 0 deletions code/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions code/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "code"
version = "0.1.0"
edition = "2021"

[dependencies]
24 changes: 24 additions & 0 deletions code/examples/misc_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![allow(unreachable_code)]

struct PrintOnDrop(&'static str);
impl Drop for PrintOnDrop {
fn drop(&mut self) {
print!("{}", self.0);
}
}

fn main() {
owo();
uwu();
}

fn owo() {
(
(PrintOnDrop("1"), PrintOnDrop("2"), PrintOnDrop("3")),
return,
);
}

fn uwu() {
(PrintOnDrop("1"), PrintOnDrop("2"), PrintOnDrop("3"), return);
}
13 changes: 13 additions & 0 deletions code/examples/trait_solver_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trait Trait {}

impl Trait for for<'a> fn(&'a u32) {}

fn f()
where
for<'a> fn(&'a u32): Trait,
{
}

fn main() {
f();
}
31 changes: 31 additions & 0 deletions code/examples/trait_solver_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
struct A;
struct B;
struct C;

trait Trait<'a, T> {
type Assoc;
}

trait Bound {}

impl Bound for B {}
impl Bound for C {}

impl<'a> Trait<'a, B> for A {
type Assoc = B;
}

impl<'a> Trait<'a, C> for A {
type Assoc = C;
}

fn f<T>(_: T)
where
for<'a> A: Trait<'a, T>,
for<'a> <A as Trait<'a, T>>::Assoc: Bound,
{
}

fn main() {
f(B);
}
18 changes: 18 additions & 0 deletions code/examples/trait_solver_3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
trait TraitA {}
trait TraitB<T: Sized> {}

impl TraitA for &dyn TraitB<[u8]> {}

trait MyDefault {
fn default() -> Self;
}

impl<T: TraitA> MyDefault for T {
fn default() -> T {
todo!("not important for the example")
}
}

fn main() {
<&dyn TraitB<[u8]> as MyDefault>::default();
}
17 changes: 17 additions & 0 deletions code/examples/trait_solver_4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
trait A<'a> {
type Assoc;
}

trait B {}

fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}

impl<'a> A<'a> for () {
type Assoc = &'a u8;
}

impl B for &u8 {}

fn main() {
f(());
}
8 changes: 8 additions & 0 deletions code/examples/trait_solver_5.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
trait Super {}
trait Sub<T>: Super {}

trait Overlap<T> {}
impl<T, U: Sub<T>> Overlap<T> for U {}
impl<T> Overlap<T> for () {}

fn main() {}
11 changes: 11 additions & 0 deletions code/examples/trait_solver_6.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn func(a: &u32) {
dbg!(a);
}

fn accepts_func(b: fn(&u32), c: &u32) {
b(c);
}

fn main() {
accepts_func(func as fn(_), &23);
}
16 changes: 16 additions & 0 deletions code/examples/trait_solver_7.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
trait Cat {}

// meow!
impl<T> Cat for T {}

fn main() {
let r = &0;
require_box(Box::new(r));

let local = 0;
let r = &local;
require_box(Box::new(r));
}

// Cats love boxes.
fn require_box(_a: Box<dyn Cat>) {}
8 changes: 8 additions & 0 deletions code/examples/unsafe_1_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![allow(deref_nullptr)]

fn main() {
// 1. UB?
unsafe {
_ = *std::ptr::null::<u32>();
}
}
8 changes: 8 additions & 0 deletions code/examples/unsafe_1_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![allow(deref_nullptr, unused_parens)]

fn main() {
// 2. UB?
unsafe {
_ = (*std::ptr::null::<u32>());
}
}
8 changes: 8 additions & 0 deletions code/examples/unsafe_1_3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![allow(deref_nullptr, unused_braces)]

fn main() {
// 3. UB?
unsafe {
_ = { *std::ptr::null::<u32>() };
}
}
6 changes: 6 additions & 0 deletions code/examples/unsafe_1_4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![allow(deref_nullptr)]

fn main() {
// 4. UB?
_ = unsafe { *std::ptr::null::<u32>() };
}
20 changes: 20 additions & 0 deletions code/examples/unsafe_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::mem::MaybeUninit;

fn main() {
// Safety: all bitpatterns are valid for u32
let random_number: u8 = unsafe { MaybeUninit::uninit().assume_init() };

let very_random_number = if random_number <= 100 {
unsafe {
// Safety: all bitpatterns are valid for u32
let rng_array: [u32; 100] = MaybeUninit::uninit().assume_init();
// Safety: The `random_number` is in bounds
*rng_array.get_unchecked(random_number as usize)
}
} else {
// chosen by a fair dice roll
4
};

dbg!(very_random_number);
}
3 changes: 3 additions & 0 deletions code/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}
12 changes: 10 additions & 2 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@
# Unsafe

- [Unsafe 1](./unsafe/1.md)
- [Unsafe 2](./unsafe/2.md)
- [Unsafe 3](./unsafe/3.md)

# Miscellaneous

- [Miscellaneous 1](./misc/1.md)

# Type System
# Trait Solver

- [Types 1](./types/1.md)
- [Trait Solver 1](./trait_solver/1.md)
- [Trait Solver 2](./trait_solver/2.md)
- [Trait Solver 3](./trait_solver/3.md)
- [Trait Solver 4](./trait_solver/4.md)
- [Trait Solver 5](./trait_solver/5.md)
- [Trait Solver 6](./trait_solver/6.md)
- [Trait Solver 7](./trait_solver/7.md)
24 changes: 2 additions & 22 deletions src/misc/1.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,9 @@
# Miscellaneous 1

The idea for this question was suggested by [`@orlp`](https://github.com/orlp/).
# Miscellaneous 1 @orlp @Nilstrieb

What does this program print?

```rust
struct PrintOnDrop(&'static str);
impl Drop for PrintOnDrop {
fn drop(&mut self) {
print!("{}", self.0);
}
}

fn main() {
owo();
uwu();
}

fn owo() {
((PrintOnDrop("1"), PrintOnDrop("2"), PrintOnDrop("3")), return);
}

fn uwu() {
(PrintOnDrop("1"), PrintOnDrop("2"), PrintOnDrop("3"), return);
}
{{#include ../../code/examples/misc_1.rs}}
```

<details>
Expand Down
23 changes: 23 additions & 0 deletions src/trait_solver/1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Trait Solver 1 @BoxyUwU @WaffleLapkin

```rust
{{#include ../../code/examples/trait_solver_1.rs}}
```

<details>
<summary>Solution</summary>

```
error: implementation of `Trait` is not general enough
--> examples/trait_solver_1.rs:12:5
|
12 | f();
| ^^^ implementation of `Trait` is not general enough
|
= note: `for<'a> fn(&'a u32)` must implement `Trait`, for any lifetime `'0`...
= note: ...but `Trait` is actually implemented for the type `for<'a> fn(&'a u32)`
```

<!-- FIXME: explanation -->

</details>
42 changes: 42 additions & 0 deletions src/trait_solver/2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Trait Solver 2 @BoxyUwU @WaffleLapkin

```rust
{{#include ../../code/examples/trait_solver_2.rs}}
```

<details>
<summary>Solution</summary>

```
error[E0277]: the trait bound `for<'a> <A as Trait<'a, _>>::Assoc: Bound` is not satisfied
--> examples/trait_solver_2.rs:30:7
|
30 | f(B);
| - ^ the trait `for<'a> Bound` is not implemented for `<A as Trait<'a, _>>::Assoc`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Bound`:
B
C
note: this is a known limitation of the trait solver that will be lifted in the future
--> examples/trait_solver_2.rs:30:7
|
30 | f(B);
| --^-
| | |
| | the trait solver is unable to infer the generic types that should be inferred from this argument
| add turbofish arguments to this call to specify the types manually, even if it's redundant
note: required by a bound in `f`
--> examples/trait_solver_2.rs:25:41
|
22 | fn f<T>(_: T)
| - required by a bound in this function
...
25 | for<'a> <A as Trait<'a, T>>::Assoc: Bound,
| ^^^^^ required by this bound in `f`
```

<!-- FIXME: explanation -->

</details>
28 changes: 28 additions & 0 deletions src/trait_solver/3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Trait Solver 3 @BoxyUwU @WaffleLapkin

```rust
{{#include ../../code/examples/trait_solver_3.rs}}
```

<details>
<summary>Solution</summary>

```
Compiling code v0.1.0 (.../rust-quiz/code)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29s
Running `target/debug/examples/trait_solver_3`
thread 'main' panicked at examples/trait_solver_3.rs:12:9:
not yet implemented: not important for the example
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

Yeah. This actually runs.

(:

The compiler does not check "Well Formedness" of traits in trait objects, so `dyn Trait<[u8]>` does not produce an error, even though `[u8]` is **not** `Sized`.

This is might be unsound, but no one come up with an example of causing UB in safe code with this.
At the very least, this is unexpected.

</details>
Loading

0 comments on commit 295a39d

Please sign in to comment.