diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 289f59e1f2e28..1d5cd29be52b8 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -32,6 +32,8 @@ - [Type system](type-system.md) - [Types](types.md) + - [Dynamically Sized Types](dynamically-sized-types.md) + - [Interior mutability](interior-mutability.md) - [Subtyping](subtyping.md) - [Type coercions](type-coercions.md) diff --git a/src/dynamically-sized-types.md b/src/dynamically-sized-types.md new file mode 100644 index 0000000000000..0933a688afc93 --- /dev/null +++ b/src/dynamically-sized-types.md @@ -0,0 +1,32 @@ +# Dynamically Sized Types + +Most types have a fixed size that is known at compile time and implement the +trait [`Sized`][sized]. A type with a size that is known only at run-time is +called a _dynamically sized type_ (_DST_) or (informally) an unsized type. +[Slices] and [trait objects] are two examples of DSTs. Such types can only be used in certain cases: + +* [Pointer types] to DSTs are + sized but have twice the size of pointers to sized types + * Pointers to slices also store the number of elements of the slice. + * Pointers to trait objects also store a pointer to a vtable. +* DSTs can be provided as + type arguments when a bound of `?Sized`. By default any type parameter + has a `?Sized` bound. +* Traits may be implemented for DSTs. Unlike type parameters`Self: ?Sized` by default in trait + definitions. +* Structs may contain a DST as the + last field, this makes the struct itself a + DST. + +Notably: [variables], function parameters, [const] and [static] items must be +`Sized`. + +[sized]: the-sized-trait.html +[Slices]: #array-and-slice-types +[trait objects]: #trait-objects +[Pointer types]: #pointer-types +[variables]: variables.html +[const]: items.html#constant-items +[static]: items.html#static-items diff --git a/src/interior-mutability.md b/src/interior-mutability.md new file mode 100644 index 0000000000000..e7543ac5a273e --- /dev/null +++ b/src/interior-mutability.md @@ -0,0 +1,30 @@ +# Interior Mutability + +Sometimes a type needs be mutated while having multiple aliases, in Rust this +is achieved using a pattern called _interior mutability_. A type has interior +mutability if its internal state can be changed through a [shared reference] to +it. This goes against the usual [requirement][ub] that the value pointed to by a +shared reference is not mutated. + +[`std::cell::UnsafeCell`] type is the only legal way in Rust to disable this +requirement. When `UnsafeCell` is immutably aliased, it is still safe to +mutate, or obtain a mutable reference to, the `T` it contains. As with all +other types, it is undefined behavior to have multiple `&mut UnsafeCell` +aliases. + +Other types with interior mutability can be created by using `UnsafeCell` as +a field. The standard library provides a variety of types that provide safe +interior mutability APIs. For example, [`std::cell::RefCell`] uses run-time +borrow checks to ensure the usual rules around multiple references. The +[`std::sync::atomic`] module contains types that wrap a value that is only +accessed with atomic operations, allowing the value to be shared and mutated +across threads. + +[shared reference]: types.hmtl#shared-references +[ub]: behavior-considered-undefined.html +[`std::mem::transmute`]: ../std/mem/fn.transmute.html +[`std::cell::UnsafeCell`]: ../std/cell/struct.UnsafeCell.html +[`std::cell::RefCell`]: ../std/cell/struct.RefCell.html +[`std::sync::atomic`]: ../std/sync/atomic.html + + diff --git a/src/types.md b/src/types.md index 10d655f7c626b..900bf0d2626a7 100644 --- a/src/types.md +++ b/src/types.md @@ -3,21 +3,44 @@ Every variable, item and value in a Rust program has a type. The _type_ of a *value* defines the interpretation of the memory holding it. -Built-in types and type-constructors are tightly integrated into the language, -in nontrivial ways that are not possible to emulate in user-defined types. -User-defined types have limited capabilities. +Built-in types are tightly integrated into the language, in nontrivial ways +that are not possible to emulate in user-defined types. User-defined types have +limited capabilities. ## Primitive types -The primitive types are the following: +Some types are defined by the language, rather than as part of the standard +library, these are called _primitive types_. Some of these are induvidual +types: * The boolean type `bool` with values `true` and `false`. -* The machine types (integer and floating-point). -* The machine-dependent integer types. -* Arrays -* Tuples -* Slices -* Function pointers +* The [machine types] (integer and floating-point). +* The [machine-dependent integer types]. +* The [textual types] `char` and `str`. + +There are also some primitive constructs for generic types built in to the +language: + +* [Tuples] +* [Arrays] +* [Slices] +* [Function pointers] +* [References] +* [Pointers] + +[machine types]: #machine-types +[machine-dependent integer types]: #machine-dependent-integer-types +[textual types]: #textual-types +[Tuples]: #tuple-types +[Arrays]: #array-and-slice-types +[Slices]: #array-and-slice-types +[References]: #pointer-types +[Pointers]: #raw-pointers +[Function pointers]: #function-pointer-types +[function]: #function-types +[closure]: #closure-types + +## Numeric types ### Machine types @@ -52,14 +75,14 @@ The types `char` and `str` hold textual data. A value of type `char` is a [Unicode scalar value]( http://www.unicode.org/glossary/#unicode_scalar_value) (i.e. a code point that -is not a surrogate) represented as a 32-bit unsigned word in the 0x0000 to -0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively a UCS-4 / -UTF-32 string. +is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to +0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` is effectively a UCS-4 / UTF-32 +string. A value of type `str` is a Unicode string, represented as an array of 8-bit -unsigned bytes holding a sequence of UTF-8 code points. Since `str` is of -unknown size, it is not a _first-class_ type, but can only be instantiated -through a pointer type, such as `&str`. +unsigned bytes holding a sequence of UTF-8 code points. Since `str` is a +[dynamically sized type], it is not a _first-class_ type, but can only be +instantiated through a pointer type, such as `&str`. ## Tuple types @@ -70,8 +93,8 @@ Tuple types and values are denoted by listing the types or values of their elements, respectively, in a parenthesized, comma-separated list. Because tuple elements don't have a name, they can only be accessed by -pattern-matching or by using `N` directly as a field to access the -`N`th element. +pattern-matching or by using `N` directly as a field to access the `N`th +element. An example of a tuple type and its use: @@ -94,13 +117,18 @@ is often called ‘unit’ or ‘the unit type’. Rust has two different types for a list of items: * `[T; N]`, an 'array' -* `&[T]`, a 'slice' +* `[T]`, a 'slice' An array has a fixed size, and can be allocated on either the stack or the heap. -A slice is a 'view' into an array. It doesn't own the data it points -to, it borrows it. +A slice is a [dynamically sized type] representing a 'view' into an array. To +use a slice type it generally has to be used behind a pointer for example as + +* `&[T]`, a 'shared slice', often just called a 'slice', it doesn't own the + data it points to, it borrows it. +* `&mut [T]`, a 'mutable slice', mutably borrows the data it points to. +* `Box<[T]>`, a 'boxed slice' Examples: @@ -108,86 +136,104 @@ Examples: // A stack-allocated array let array: [i32; 3] = [1, 2, 3]; -// A heap-allocated array -let vector: Vec = vec![1, 2, 3]; +// A heap-allocated array, coerced to a slice +let boxed_array: Box<[i32]> = Box::new([1, 2, 3]); -// A slice into an array -let slice: &[i32] = &vector[..]; +// A (shared) slice into an array +let slice: &[i32] = &boxed_array[..]; ``` -As you can see, the `vec!` macro allows you to create a `Vec` easily. The -`vec!` macro is also part of the standard library, rather than the language. +All elements of arrays and slices are always initialized, and access to an +array or slice is always bounds-checked in safe methods and operators. + +The [`Vec`] standard library type provides a heap allocated resizable array +type. -All in-bounds elements of arrays and slices are always initialized, and access -to an array or slice is always bounds-checked. +[dynamically sized type]: dynamically-sized-types.html +[`Vec`]: ../std/vec/struct.Vec.html ## Struct types A `struct` *type* is a heterogeneous product of other types, called the *fields* of the type.[^structtype] -[^structtype]: `struct` types are analogous to `struct` types in C, - the *record* types of the ML family, - or the *struct* types of the Lisp family. - New instances of a `struct` can be constructed with a [struct expression](expressions.html#struct-expressions). The memory layout of a `struct` is undefined by default to allow for compiler optimizations like field reordering, but it can be fixed with the -`#[repr(...)]` attribute. In either case, fields may be given in any order in -a corresponding struct *expression*; the resulting `struct` value will always +`#[repr(...)]` attribute. In either case, fields may be given in any order in a +corresponding struct *expression*; the resulting `struct` value will always have the same memory layout. The fields of a `struct` may be qualified by [visibility -modifiers](visibility-and-privacy.html), to allow access to data in a -struct outside a module. +modifiers](visibility-and-privacy.html), to allow access to data in a struct +outside a module. A _tuple struct_ type is just like a struct type, except that the fields are anonymous. -A _unit-like struct_ type is like a struct type, except that it has no -fields. The one value constructed by the associated [struct -expression](expressions.html#struct-expressions) is the only value that inhabits such a -type. +A _unit-like struct_ type is like a struct type, except that it has no fields. +The one value constructed by the associated [struct +expression](expressions.html#struct-expressions) is the only value that +inhabits such a type. + +[^structtype]: `struct` types are analogous to `struct` types in C, the + *record* types of the ML family, or the *struct* types of the Lisp family. ## Enumerated types An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted by the name of an [`enum` item](items.html#enumerations). [^enumtype] +An [`enum` item](items.html#enumerations) declares both the type and a number +of *variants*, each of which is independently named and has the syntax of a +struct, tuple struct or unit-like struct. + +New instances of an `enum` can be constructed in an [enumeration variant +expression](expressions.html#enumeration-variant-expressions). + +Any `enum` value consumes as much memory as the largest variant for its +corresponding `enum` type, as well as the size needed to store a discriminant. + +Enum types cannot be denoted *structurally* as types, but must be denoted by +named reference to an [`enum` item](items.html#enumerations). + [^enumtype]: The `enum` type is analogous to a `data` constructor declaration in ML, or a *pick ADT* in Limbo. -An [`enum` item](items.html#enumerations) declares both the type and a number of *variant -constructors*, each of which is independently named and takes an optional tuple -of arguments. +## Union types -New instances of an `enum` can be constructed by calling one of the variant -constructors, in a [call expression](expressions.html#call-expressions). +A *union type* is a nominal, heterogeneous C-like union, denoted by the name of +a [`union` item](items.html#unions). -Any `enum` value consumes as much memory as the largest variant constructor for -its corresponding `enum` type. +A union contains the value of any one of its fields. Since the accessing the +wrong field can cause unexpected or undefined behaviour, `unsafe` is required +to read from a union field or to write to a field that doesn't implement +[`Copy`]. -Enum types cannot be denoted *structurally* as types, but must be denoted by -named reference to an [`enum` item](items.html#enumerations). +The memory layout of a `union` is undefined by default, but the `#[repr(...)]` +attribute can be used to fix a layout. + +[`Copy`]: the-copy-trait.html ## Recursive types -Nominal types — [enumerations](#enumerated-types) and -[structs](#struct-types) — may be recursive. That is, each `enum` -constructor or `struct` field may refer, directly or indirectly, to the -enclosing `enum` or `struct` type itself. Such recursion has restrictions: - -* Recursive types must include a nominal type in the recursion - (not mere [type definitions](../grammar.html#type-definitions), - or other structural types such as [arrays](#array-and-slice-types) or [tuples](#tuple-types)). -* A recursive `enum` item must have at least one non-recursive constructor - (in order to give the recursion a basis case). -* The size of a recursive type must be finite; - in other words the recursive fields of the type must be [pointer types](#pointer-types). -* Recursive type definitions can cross module boundaries, but not module *visibility* boundaries, - or crate boundaries (in order to simplify the module system and type checker). +Nominal types — [structs](#struct-types), +[enumerations](#enumerated-types) and [unions](#union-types) — may be +recursive. That is, each `enum` variant or `struct` or `union` field may refer, +directly or indirectly, to the enclosing `enum` or `struct` type itself. Such +recursion has restrictions: + +* Recursive types must include a nominal type in the recursion (not mere [type + definitions](../grammar.html#type-definitions), or other structural types + such as [arrays](#array-and-slice-types) or [tuples](#tuple-types)). So + `type Rec = &'static [Rec]` is not allowed. +* The size of a recursive type must be finite; in other words the recursive + fields of the type must be [pointer types](#pointer-types). +* Recursive type definitions can cross module boundaries, but not module + *visibility* boundaries, or crate boundaries (in order to simplify the module + system and type checker). An example of a *recursive* type and its use: @@ -202,62 +248,78 @@ let a: List = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil)))); ## Pointer types -All pointers in Rust are explicit first-class values. They can be copied, -stored into data structs, and returned from functions. There are two -varieties of pointer in Rust: - -* References (`&`) - : These point to memory _owned by some other value_. - A reference type is written `&type`, - or `&'a type` when you need to specify an explicit lifetime. - Copying a reference is a "shallow" operation: - it involves only copying the pointer itself. - Releasing a reference has no effect on the value it points to, - but a reference of a temporary value will keep it alive during the scope - of the reference itself. - -* Raw pointers (`*`) - : Raw pointers are pointers without safety or liveness guarantees. - Raw pointers are written as `*const T` or `*mut T`, - for example `*const i32` means a raw pointer to a 32-bit integer. - Copying or dropping a raw pointer has no effect on the lifecycle of any - other value. Dereferencing a raw pointer or converting it to any other - pointer type is an [`unsafe` operation](unsafe-functions.html). - Raw pointers are generally discouraged in Rust code; - they exist to support interoperability with foreign code, - and writing performance-critical or low-level functions. +All pointers in Rust are explicit first-class values. They can be moved or +copied, stored into data structs, and returned from functions. + +### Shared references (`&`) + +These point to memory _owned by some other value_. When a shared reference to a +value is created it prevents direct mutation of the value. [Interior +mutability](interior-mutability.html) provides an exception for this in certain +circumstances. As the name suggests, any number of shared references to a value +may exit. A shared reference type is written `&type`, or `&'a type` when you +need to specify an explicit lifetime. Copying a reference is a "shallow" +operation: it involves only copying the pointer itself, that is, pointers are +`Copy`. Releasing a reference has no effect on the value it points to, but +referencing of a [temporary value](expressions.html#temporary-lifetimes) will +keep it alive during the scope of the reference itself. + +### Mutable references (`&mut`) + +These also point to memory owned by some other value. A mutable reference type +is written `&mut type` or `&'a mut type`. A mutable reference (that hasn't been +borrowed) is the only way to access the value it points to, so is not `Copy`. + +### Raw pointers (`*const` and `*mut`) + +Raw pointers are pointers without safety or liveness guarantees. Raw pointers +are written as `*const T` or `*mut T`, for example `*const i32` means a raw +pointer to a 32-bit integer. Copying or dropping a raw pointer has no effect on +the lifecycle of any other value. Dereferencing a raw pointer is an [`unsafe` +operation](unsafe-functions.html), this can also be used to convert a raw +pointer to a reference by reborrowing it (`&*` or `&mut *`). Raw pointers are +generally discouraged in Rust code; they exist to support interoperability with +foreign code, and writing performance-critical or low-level functions. + +When comparing pointers they are compared by their address, rather than by what +they point to. When comparing pointers to [dynamically sized +types](dynamically-sized-types.html) they also have their addition data +compared. + +### Smart Pointers The standard library contains additional 'smart pointer' types beyond references and raw pointers. ## Function item types -When referred to, a function item yields a zero-sized value of its -_function item type_. That type explicitly identifies the function - its name, -its type arguments, and its early-bound lifetime arguments (but not its -late-bound lifetime arguments, which are only assigned when the function -is called) - so the value does not need to contain an actual function pointer, -and no indirection is needed when the function is called. +When referred to, a function item, or the constructor of a tuple-like struct or +enum variant, yields a zero-sized value of its _function item type_. That type +explicitly identifies the function - its name, its type arguments, and its +early-bound lifetime arguments (but not its late-bound lifetime arguments, +which are only assigned when the function is called) - so the value does not +need to contain an actual function pointer, and no indirection is needed when +the function is called. There is currently no syntax that directly refers to a function item type, but -the compiler will display the type as something like `fn() {foo::}` in error -messages. +the compiler will display the type as something like `fn() {foo::}` in +error messages. Because the function item type explicitly identifies the function, the item types of different functions - different items, or the same item with different generics - are distinct, and mixing them will create a type error: -```rust,ignore +```rust,compile_fail,E0308 fn foo() { } let x = &mut foo::; *x = foo::; //~ ERROR mismatched types ``` -However, there is a [coercion] from function items to [function pointers](#function-pointer-types) -with the same signature, which is triggered not only when a function item -is used when a function pointer is directly expected, but also when different -function item types with the same signature meet in different arms of the same -`if` or `match`: +However, there is a [coercion] from function items to [function +pointers](#function-pointer-types) with the same signature, which is triggered +not only when a function item is used when a function pointer is directly +expected, but also when different function item types with the same signature +meet in different arms of the same `if` or `match`: [coercion]: type-coercions.html @@ -278,16 +340,16 @@ let foo_ptr_2 = if want_i32 { ## Function pointer types -Function pointer types, created using the `fn` type constructor, refer -to a function whose identity is not necessarily known at compile-time. They -can be created via a coercion from both [function items](#function-item-types) -and non-capturing [closures](#closure-types). +Function pointer types, written using the `fn` keyword, refer to a function +whose identity is not necessarily known at compile-time. They can be created +via a coercion from both [function items](#function-item-types) and +non-capturing [closures](#closure-types). A function pointer type consists of a possibly-empty set of function-type modifiers (such as `unsafe` or `extern`), a sequence of input types and an output type. -An example of a `fn` type: +An example where `Binop` is defined as a function pointer type: ```rust fn add(x: i32, y: i32) -> i32 { @@ -310,23 +372,24 @@ Depending on the requirements of the closure, its type implements one or more of the closure traits: * `FnOnce` - : The closure can be called once. A closure called as `FnOnce` - can move out values from its environment. + : The closure can be called once. A closure called as `FnOnce` can move out + of its captured values. * `FnMut` : The closure can be called multiple times as mutable. A closure called as `FnMut` can mutate values from its environment. `FnMut` inherits from `FnOnce` (i.e. anything implementing `FnMut` also implements `FnOnce`). -* `Fn` - : The closure can be called multiple times through a shared reference. - A closure called as `Fn` can neither move out from nor mutate values - from its environment, but read-only access to such values is allowed. - `Fn` inherits from `FnMut`, which itself inherits from `FnOnce`. +* `Fn` : The closure can be called multiple times through a shared reference. A + closure called as `Fn` can neither move out from nor mutate captured + variables, but read-only access to such values is allowed. Using `move` to + capture variables by value is allowed so long as they aren't mutated or + moved in the body of the closure. `Fn` inherits from `FnMut`, which itself + inherits from `FnOnce`. -Closures that don't use anything from their environment ("non capturing closures") -can be coerced to function pointers (`fn`) with the matching signature. -To adopt the example from the section above: +Closures that don't use anything from their environment ("non capturing +closures") can be coerced to function pointers (`fn`) with the matching +signature. To adopt the example from the section above: ```rust let add = |x, y| x + y; @@ -340,8 +403,12 @@ x = bo(5,7); ## Trait objects -In Rust, a type like `&SomeTrait` or `Box` is called a _trait object_. -Each instance of a trait object includes: +In Rust, trait names also refer to [dynamically sized types] called _trait +objects_. Like all DSTs, trait +objects are used behind some kind of pointer: `&SomeTrait` or `Box`. +Each instance of a pointer to a trait object includes: + +[dynamically sized types]: dynamically-sized-types.html - a pointer to an instance of a type `T` that implements `SomeTrait` - a _virtual method table_, often just called a _vtable_, which contains, for @@ -354,11 +421,18 @@ function pointer is loaded from the trait object vtable and invoked indirectly. The actual implementation for each vtable entry can vary on an object-by-object basis. -Note that for a trait object to be instantiated, the trait must be -_object-safe_. Object safety rules are defined in [RFC 255]. +Note that trait object types only exist for _object-safe_ traits ([RFC 255]): [RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md +* It must not require `Self: Sized` +* All associated functions must either have a `where Self: Sized` bound or + * Not have any type parameters (lifetime parameters are allowed) + * Must be a method: its first parameter must be called self, with type + `Self`, `&Self`, `&mut Self`, `Box`. + * `Self` may only be used in the type of the receiver. +* It must not have any associated constants. + Given a pointer-typed expression `E` of type `&T` or `Box`, where `T` implements trait `R`, casting `E` to the corresponding pointer type `&R` or `Box` results in a value of the _trait object_ `R`. This result is @@ -396,28 +470,45 @@ These were defined in [RFC 599] and amended in [RFC 1156]. [RFC 599]: https://github.com/rust-lang/rfcs/blob/master/text/0599-default-object-bound.md [RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md -For traits that themselves have no lifetime parameters, the default bound is -based on what kind of trait object is used: +For traits that themselves have no lifetime parameters: +* If there is a unique bound from the containing type then that is the default +* If there is more than one bound from the containing type then an explicit bound must + be specified +* Otherwise the default bound is `'static` ```rust,ignore // For the following trait... trait Foo { } -// ...these two are the same: +// These two are the same as Box has no lifetime bound on T Box Box // ...and so are these: +impl Foo {} +impl Foo + 'static {} + +// ...so are these, because &'a T requires T: 'a &'a Foo &'a (Foo + 'a) + +// std::cell::Ref<'a, T> also requires T: 'a, so these are the same +std::cell::Ref<'a, Foo> +std::cell::Ref<'a, Foo + 'a> + +// This is an error: +struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b> +TwoBounds<'a, 'b, Foo> // Error: the lifetime bound for this object type cannot + // be deduced from context + ``` The `+ 'static` and `+ 'a` refer to the default bounds of those kinds of trait objects, and also to how you can directly override them. Note that the innermost object sets the bound, so `&'a Box` is still `&'a Box`. -For traits that have lifetime parameters of their own, the default bound is -based on that lifetime parameter: +For traits that have a single lifetime _bound_ of their own then, instead of +infering 'static as the default bound, the bound on the trait is used instead ```rust,ignore // For the following trait... @@ -426,15 +517,17 @@ trait Bar<'a>: 'a { } // ...these two are the same: Box> Box + 'a> -``` -The default for user-defined trait objects is based on the object type itself. -If a type parameter has a lifetime bound, then that lifetime bound becomes the -default bound for trait objects of that type. For example, `std::cell::Ref<'a, -T>` contains a `T: 'a` bound, therefore trait objects of type `Ref<'a, -SomeTrait>` are the same as `Ref<'a, (SomeTrait + 'a)>`. +// ...and so are these: +impl<'a> Foo<'a> {} +impl<'a> Foo<'a> + 'a {} + +// This is still an error: +struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b> +TwoBounds<'a, 'b, Foo<'c>> +``` -### Type parameters +## Type parameters Within the body of an item that has type parameter declarations, the names of its type parameters are types: @@ -451,14 +544,13 @@ fn to_vec(xs: &[A]) -> Vec { } ``` -Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and `rest` -has type `Vec`, a vector with element type `A`. +Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and +`rest` has type `Vec`, a vector with element type `A`. ## Self types -The special type `Self` has a meaning within traits and impls. In a trait definition, it refers -to an implicit type parameter representing the "implementing" type. In an impl, -it is an alias for the implementing type. For example, in: +The special type `Self` has a meaning within traits and impls: it refers to +the implementing type. For example, in: ```rust pub trait From { @@ -472,8 +564,8 @@ impl From for String { } ``` -The notation `Self` in the impl refers to the implementing type: `String`. In another -example: +The notation `Self` in the impl refers to the implementing type: `String`. In +another example: ```rust trait Printable { @@ -487,6 +579,4 @@ impl Printable for String { } ``` -The notation `&self` is a shorthand for `self: &Self`. In this case, -in the impl, `Self` refers to the value of type `String` that is the -receiver for a call to the method `make_string`. +The notation `&self` is a shorthand for `self: &Self`. \ No newline at end of file