Skip to content

Commit 4adfb2e

Browse files
committed
[function values] fix docs that were removed in merge changes
1 parent 8937bb0 commit 4adfb2e

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

apps/nextra/pages/en/build/smart-contracts/book/functions.mdx

+28-10
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,11 @@ script {
232232
}
233233
```
234234

235-
Entry functions can take primitive types, String, and vector arguments but cannot take Structs (e.g. Option). They also
236-
must not have any return values.
235+
Entry functions can accept parameters that are: primitive types, reference to a
236+
`signer`, vectors (where the element type is itself acceptable),
237+
and certain standard library types such as `String`, `Object`, and `Option`.
238+
Entry functions must not have any return values.
239+
237240

238241
### Name
239242

@@ -733,7 +736,22 @@ The type of the `self` argument can be a struct or an immutable or mutable refer
733736

734737
Notice that you do not need to `use` the modules which introduce receiver functions. The compiler will find those functions automatically based on the argument type of `s` in a call like `s.foo(1)`. This, in combination with the automatic insertion of reference operators, can make code using this syntax significantly more concise.
735738

736-
## Function Values
739+
The receiver style syntax can also be used on generic functions, like shown below for the generic function `std::vector::remove<T>(self: &mut vector<T>, i: u64): T`.
740+
741+
```move
742+
module 0x42::example {
743+
fun bar() {
744+
let v = vector[1, 2, 3];
745+
let e1 = v.remove(0); // type params inferred for `remove<T>`
746+
assert!(e1 == 1);
747+
let e2 = v.remove::<u8>(0); // type params explicitly specified
748+
assert!(e2 == 2);
749+
}
750+
}
751+
```
752+
753+
754+
## Function Values
737755

738756
_Since language version 2.2_ (preview)
739757

@@ -748,7 +766,7 @@ Function types can have associated abilities, written as `|u64|bool has copy`. M
748766
Function values can be stored in fields of structs or enums. In this case, the field type inherits the abilities of the struct:
749767

750768
```move
751-
struct S has key {
769+
struct S has key {
752770
func: |u64| bool /* has store */ // not needed since inherited
753771
}
754772
```
@@ -799,7 +817,7 @@ let f: |u64|bool has copy+drop+store = is_even;
799817
let g: |u64|bool has copy+drop = is_odd;
800818
```
801819

802-
A public function is required to build a storable function value because it needs to be guaranteed that the underlying function persists so the function value can be safely restored from storage at any point in the future. However, code upgrade may change the underlying implementation of the function, while its signature is persistent.
820+
A public function is required to build a storable function value because it needs to be guaranteed that the underlying function persists so the function value can be safely restored from storage at any point in the future. However, code upgrade may change the underlying implementation of the function, while its signature is persistent.
803821

804822
If a function should storable which is non-public, an attribute can be used to mark this function as persistent, with the same upgrade behavior than public functions. This avoids exposing such a function outside of a package which can be a security risk:
805823

@@ -840,11 +858,11 @@ let f: |u64|u64 has copy+drop+store = |y| add(x, y)
840858
let f: |u64|u64 has copy+drop+store = |y| add(y, x)
841859
```
842860

843-
For reference, this mechanism is also called 'currying' of `add` in functional programming languages.
861+
For reference, this mechanism is also called 'currying' of `add` in functional programming languages.
844862

845863
### Reentrancy Check
846864

847-
Via dynamic dispatch of function values, reentrancy of modules in a chain of function calls is possible. If module `m1` uses module `m2`, and `m1` calls `m2::f` passing a function value to it, this function value can callback into `m1`. This situation is called _reentrancy_, and is not possible in Move without function values, since the module usage relation is acyclic.
865+
Via dynamic dispatch of function values, reentrancy of modules in a chain of function calls is possible. If module `m1` uses module `m2`, and `m1` calls `m2::f` passing a function value to it, this function value can callback into `m1`. This situation is called _reentrancy_, and is not possible in Move without function values, since the module usage relation is acyclic.
848866

849867
The Move VM dynamically detects reentrancy for a module, and _locks_ all resources declared in this module from being accessed. Thus during reentrancy, calling the functions `borrow_global`, `borrow_global_mut`, and `move_from` lead to an abort. Here is an example:
850868

@@ -855,7 +873,7 @@ module caller {
855873
fun calling() acquires R {
856874
let r = &mut R[@addr];
857875
// This callback is OK, because `R` is not accessed
858-
callee::call_me(r, |x| do_something(x))
876+
callee::call_me(r, |x| do_something(x))
859877
// This callback will lead to reentrancy runtime error
860878
callee::call_me(r, |_| R[@addr].count += 1)
861879
r.call_count += 1
@@ -867,12 +885,12 @@ module callee {
867885
fun call_me<T(x: &mut T, action: |&mut T|) {
868886
action(x)
869887
}
870-
}
888+
}
871889
```
872890

873891
Notice that dispatching a function value to a concrete function in the same module is also considered to be reentrancy. If the function `callee::call_me` would be moved into the module `caller`, the same semantics is in effect.
874892

875-
The default reentrancy check ensures consistency of Move's reference semantics and suppresses side-effects for the resources in a reentered module. But it does not protect from side-effects on other state of the app. For this purposes, the `#[module_lock]` attribute can be attached to a function. In a calling context where this attribute is active, reentrancy will be fully suppressed, causing an abort at the moment a module is reentered. In the example below, the state effected is owned by another module `account` instead of the module `caller` for which the can potentially happen via the `notify` callback:
893+
The default reentrancy check ensures consistency of Move's reference semantics and suppresses side-effects for the resources in a reentered module. But it does not protect from side-effects on other state of the app. For this purposes, the `#[module_lock]` attribute can be attached to a function. In a calling context where this attribute is active, reentrancy will be fully suppressed, causing an abort at the moment a module is reentered. In the example below, the state effected is owned by another module `account` instead of the module `caller` for which the can potentially happen via the `notify` callback:
876894

877895
```move
878896
module account { ... }

0 commit comments

Comments
 (0)