Skip to content

Commit 7c6a72a

Browse files
committed
Fixes
1 parent b0e8f95 commit 7c6a72a

File tree

3 files changed

+24
-21
lines changed

3 files changed

+24
-21
lines changed

src/ch02-01-variables-and-mutability.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ not a good programmer! Experienced Caironautes still get compiler errors.
4141
You received the error message `Cannot assign to an immutable variable.`
4242
because you tried to assign a second value to the immutable `x` variable.
4343

44+
It’s important that we get compile-time errors when we attempt to change a
45+
value that’s designated as immutable because this specific situation can lead to
46+
bugs. If one part of our code operates on the assumption that a value will
47+
never change and another part of our code changes that value, it’s possible
48+
that the first part of the code won’t do what it was designed to do. The cause
49+
of this kind of bug can be difficult to track down after the fact, especially
50+
when the second piece of code changes the value only _sometimes_.
51+
4452
Cairo, unlike most other languages, has immutable memory. This makes a
4553
whole class of bugs impossible, because values will never change unexpectedly.
4654
This makes code easier to reason about.
@@ -49,13 +57,15 @@ But mutability can be very useful, and can make code more convenient to write.
4957
Although variables are immutable by default, you can make them mutable by
5058
adding `mut` in front of the variable name. Adding `mut` also conveys
5159
intent to future readers of the code by indicating that other parts of the code
52-
will be changing this variable.
60+
will be changing the value associated to this variable.
61+
62+
<!-- TODO: add an illustration of this -->
5363

5464
However, you might be wondering at this point what exactly happens when a variable
5565
is declared as `mut`, as we previously mentioned that Cairo's memory is immutable.
5666
The answer is that the _value_ is immutable, but the _variable_ isn't. What value
5767
the variable points to can be changed. Assigning to a mutable variable in Cairo
58-
is essentially equivalent to redeclaring it to point to another value in another memory cell,
68+
is essentially equivalent to redeclaring it to refer to another value in another memory cell,
5969
but the compiler handles that for you, and the keyword `mut` makes it explicit.
6070
Upon examining the low-level Cairo Assembly code, it becomes clear that
6171
variable mutation is implemented as syntactic sugar, which translates mutation operations

src/ch04-01-what-is-ownership.md

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
## Ownership Using a Linear Type System
22

3-
Cairo uses a linear type system for two main reasons:
4-
- Ensuring that all code is provable and thus verifiable.
5-
- Abstracting away the immutable memory of the Cairo VM.
6-
7-
In a linear type system, any value (a basic type, a struct, an enum) must be used and must only be used once. 'Used' here means that the value is either _destroyed_ or _moved_.
3+
Cairo uses a linear type system. In such a type system, any value (a basic type, a struct, an enum) must be used and must only be used once. 'Used' here means that the value is either _destroyed_ or _moved_.
84

95
_Destruction_ can happen in several ways:
106
- a variable goes out of scope
@@ -15,10 +11,13 @@ _Moving_ a value simply means passing that value to another function.
1511

1612
This results in somewhat similar constraints to the Rust ownership model, but there are some differences.
1713
In particular, the rust ownership model exists (in part) to avoid data races and concurrent mutable access to a memory value. This is obviously impossible in Cairo since the memory is immutable.
14+
Instead, Cairo leverages its linear type system for two main purposes:
15+
- Ensuring that all code is provable and thus verifiable.
16+
- Abstracting away the immutable memory of the Cairo VM.
1817

1918
#### Ownership
2019

21-
In Cairo, ownership applies to _variables_ and not to _values_. A value can safely be pointed to by many different variables (even if they are mutable variables), as the value itself is always immutable.
20+
In Cairo, ownership applies to _variables_ and not to _values_. A value can safely be referred to by many different variables (even if they are mutable variables), as the value itself is always immutable.
2221
Variables however can be mutable, so the compiler must ensure that constant variables aren't accidentally modified by the programmer.
2322
This makes it possible to talk about ownership of a variable: the owner is the code that can read (and write if mutable) the variable.
2423

@@ -74,13 +73,12 @@ Here is a short reminder of what an array looks like:
7473
How does the type system ensure that the Cairo program never tries to write to the same memory cell twice?
7574
Consider the following code, where we try to remove the front of the array twice:
7675

77-
//// CHANGEME
7876
```rust,does_not_compile
7977
{{#include ../listings/ch04-understanding-ownership/no_listing_02_pass_array_by_value/src/lib.cairo}}
8078
```
8179

82-
In this case, we try to pass the same value (the array in `arr`) to both function calls. This means our code tries to remove the first element twice, which would try to write to the same memory cell twice - which is forbidden by the Cairo VM, leading to a runtime error.
83-
Thankfully, this code does not actually compile. Once we have passed the array, the variable is no longer usable. We get this compile-time error, telling us that we would need Array to implement the Copy Trait:
80+
In this case, we try to pass the same value (the array in the `arr` variable) to both function calls. This means our code tries to remove the first element twice, which would try to write to the same memory cell twice - which is forbidden by the Cairo VM, leading to a runtime error.
81+
Thankfully, this code does not actually compile. Once we have passed the array to the `foo` function, the variable `arr` is no longer usable. We get this compile-time error, telling us that we would need Array to implement the Copy Trait:
8482

8583
```shell
8684
error: Variable was previously moved. Trait has no implementation in context: core::traits::Copy::<core::array::Array::<core::integer::u128>>
@@ -101,15 +99,15 @@ While Arrays and Dictionaries can't be copied, custom types that don't contain e
10199
{{#include ../listings/ch04-understanding-ownership/no_listing_03_copy_trait/src/lib.cairo}}
102100
```
103101

104-
In this example, we can pass `p1` twice to the foo function because the `Point` type implements the `Copy` trait. This means that when we pass `p1` to `foo`, we are actually passing a copy of `p1`, so `p1` remains valid.
102+
In this example, we can pass `p1` twice to the foo function because the `Point` type implements the `Copy` trait. This means that when we pass `p1` to `foo`, we are actually passing a copy of `p1`, so `p1` remains valid. In ownership terms, this means that the ownership of `p1` remains with the main function.
105103
If you remove the `Copy` trait derivation from the `Point` type, you will get a compile-time error when trying to compile the code.
106104

107105
_Don't worry about the `Struct` keyword. We will introduce this in [Chapter 5](ch05-00-using-structs-to-structure-related-data.md)._
108106

109107
### Destroying values - example with FeltDict
110108

111109
The other way linear types can be _used_ is by being destroyed. Destruction must ensure that the 'resource' is now correctly released. In rust for example, this could be closing the access to a file, or locking a mutex.
112-
In Cairo, one type that has such behaviour is felt252Dict. For provability, dicts must be 'squashed' when they are destructed.
110+
In Cairo, one type that has such behaviour is `Felt252Dict`. For provability, dicts must be 'squashed' when they are destructed.
113111
This would be very easy to forget, so it is enforced by the type system and the compiler.
114112

115113
#### No-op destruction: the Drop Trait
@@ -130,9 +128,9 @@ For example, the following code compiles:
130128
```
131129

132130
#### Destruction with a side-effect: the Destruct trait
133-
When a value is destroyed, the compiler calls the `destruct` method on that type. This method is provided by the `Destruct` trait. This is actually how `Drop` is implemented at the moment, by providing a `Destruct` impl that does nothing.
131+
When a value is destroyed, the compiler first tries to call the `drop` method on that type. If it doesn't exist, then the compiler tries to call `destruct` instead. This method is provided by the `Destruct` trait.
134132

135-
As said earlier, dictionaries in Cairo are types that must be "squashed" when destructed, so that the sequence of access can be proven. This is easy for developers to forget, so instead dictionaries implement the Destruct Trait.
133+
As said earlier, dictionaries in Cairo are types that must be "squashed" when destructed, so that the sequence of access can be proven. This is easy for developers to forget, so instead dictionaries implement the `Destruct` trait to ensure that all dictionaries are _squashed_ when going out of scope.
136134
As such, the following example will not compile:
137135

138136
```rust,does_not_compile
@@ -156,11 +154,6 @@ When A goes out of scope, it can't be dropped as it implements neither the `Drop
156154
157155
Now, when `A` goes out of scope, its dictionary will be automatically `squashed`, and the program will compile.
158156
159-
#### Copy vs Destruct
160-
161-
You may notice that these two traits are somewhat incompatible. With a `Copy` type, we could have two variables pointing to the same value, which would lead to a double-destruction when both variables go out of scope. This is obviously quite broken for any type with a non-trivial `Destruct` implementation.
162-
For this reason, most types are either `Copy` and `Drop`, just `Drop`, or none. A `Copy` and `Destruct` type is possible, but be aware that this is rather odd, and possibly an indicator of a 'gotcha'.
163-
164157
### Copy Array data with Clone
165158
166159
If we _do_ want to deeply copy the data of an `Array`, we can use a common method called `clone`. We’ll discuss method syntax in Chapter 6, but because methods are a common feature in many programming languages, you’ve probably seen them before.

src/ch04-02-references-and-snapshots.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Let's see how we can retain ownership of the variable in the calling function us
1414

1515
In Cairo, a snapshot is an immutable view of a value at a certain point in time.
1616
Recall that memory is immutable, so modifying a value actually creates a new memory cell.
17-
The old memory cell still exists, and snapshots are variables that point to that "old" value.
17+
The old memory cell still exists, and snapshots are variables that refer to that "old" value.
1818
In this sense, snapshots are a view "into the past".
1919

2020
Here is how you would define and use a `calculate_length` function that takes a

0 commit comments

Comments
 (0)