# 8.6 Ownership and functions
> Passing a String to a function moves it, returning gives ownership back: the full story behind 'arguments are copied', and why chapter 9 exists.
Source: https://learnrust.net/chapter-8/ownership-and-functions/
Lesson [2.3](@/chapter-2/parameters-and-arguments.md) owes this course's readers the second half of an asterisk: "'Arguments are copied' is the whole truth for integers and the other simple types in these chapters, and a simplification for types like `String`. The full story is *the* story of this course: ownership, chapter 8." Last lesson paid the Copy half. Today: what actually happens when a `String` meets a function.
## Passing gives
You can likely predict it now. Function calls hand values to parameters the same way `=` hands values to variables, so the rules are lesson [8.4](@/chapter-8/moves.md)'s rules: Copy types copy, owners move. Passing a `String` to a function *gives it away*:
```rust
fn main() {
let order = String::from("two coffees");
submit(order);
println!("{order}");
}
fn submit(text: String) {
println!("submitted: {text}");
}
```
```
error[E0382]: borrow of moved value: `order`
--> src/main.rs:4:16
|
2 | let order = String::from("two coffees");
| ----- move occurs because `order` has type `String`, which does not implement the `Copy` trait
3 | submit(order);
| ----- value moved here
4 | println!("{order}");
| ^^^^^ value borrowed here after move
|
note: consider changing this parameter type in function `submit` to borrow instead if owning the value isn't necessary
--> src/main.rs:7:17
|
7 | fn submit(text: String) {
| ------ ^^^^^^ this parameter takes ownership of the value
| |
| in this function
help: consider cloning the value if the performance cost is acceptable
|
3 | submit(order.clone());
| ++++++++
```
The anatomy is last lesson's friend `E0382` with one new organ. The top half you can read fluently now: the move-because-`String` note, `value moved here` at the call, the illegal use after. The new part is the middle **note**, and it's remarkable: the compiler walks into `submit`'s definition, points at the parameter type, and says `this parameter takes ownership of the value`. The phrase "takes ownership" is the lesson, straight from the diagnostic: a `String` parameter doesn't receive a copy, it receives *the value itself*, and the caller's variable is left moved-from.
And look at the compiler's first suggestion: change the parameter "to borrow instead." That word is chapter 9's entire subject. When the diagnostics start advertising the next chapter, you're reading the course in the right order.
What happens to `order`'s value if the call *is* legal (drop the fourth line)? `text` owns it now. `text` is a local of `submit`, so at `submit`'s closing brace, the value is dropped, heap block returned (lesson [8.3](@/chapter-8/scope-and-drop.md)). Handing a value to a function really is giving it away: by default, the function keeps it, uses it, and disposes of it.
Meanwhile, for Copy types nothing changed all chapter:
```rust
fn main() {
let count = 12;
report(count);
println!("still here: {count}");
}
fn report(n: u32) {
println!("counted {n}");
}
```
```
counted 12
still here: 12
```
Lesson [2.3](@/chapter-2/parameters-and-arguments.md)'s asterisk is now fully cashed: arguments are copied when the type is Copy, and moved when it isn't. That is the complete truth, no asterisks remaining.
## Returning gives back
Moves flow out of functions too. A `return` (or tail expression) moves the value to the caller, which is the proper description of a function you wrote in lesson [5.x](@/chapter-5/chapter-5-summary-and-quiz.md)'s capstone:
```rust
use std::io;
fn read_name() -> String {
println!("Name?");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("failed to read input");
String::from(input.trim())
}
fn main() {
let name = read_name();
println!("hello, {name}");
}
```
```
Name?
hello, Ada
```
In chapter 5 the justification was intuition: "the caller is keeping the text, so a view of the function's local input wouldn't survive." Now every word has machinery under it. `input` is owned by `read_name` and dies at its closing brace; a view into it could outlive the text (chapter 9 makes that a compile error, as promised). But `String::from(input.trim())` builds a *new owned value*, and the tail expression moves it out to `main`, where `name` becomes its owner. Ownership flowed in neither direction by copy: the function built a value and *gave* it to its caller.
This also settles a chapter 5 style rule properly. Lesson [5.4](@/chapter-5/introduction-to-str.md) said `String` parameters are for functions that *keep* the text. Now you can say it with this chapter's vocabulary: a `String` parameter means "I take ownership"; a `&str` parameter means "I only look." Functions that merely read text should ask for the view. Functions that will own it (store it, consume it, return it transformed) ask for the `String`, and the move at the call site is the honest record of that transfer.
## The give-and-take-back dance
But what if a function needs to *use* a `String` and the caller needs it *afterwards*? With only this chapter's tools, the function must hand it back, and since it also wants to return its actual result, you reach for lesson [4.11](@/chapter-4/tuples-and-the-unit-type.md)'s tuples:
```rust
fn measure(text: String) -> (String, usize) {
let bytes = text.len();
(text, bytes)
}
fn main() {
let name = String::from("Ada Lovelace");
let (name, bytes) = measure(name);
println!("{name} is {bytes} bytes long");
}
```
```
Ada Lovelace is 12 bytes long
```
It compiles, it runs, and it is *awkward on purpose*. Look at the bookkeeping: the function's real job returns one `usize`, but its signature drags the `String` along like a deposit being refunded, and the caller re-binds `name` (a shadowing `let`, lesson [5.2](@/chapter-5/shadowing.md)) just to receive its own value back. Imagine three string parameters. Imagine doing this in every function in a real program.
Rust programmers do not live like this, and the compiler already told you the way out, in this lesson's first error message: *"consider changing this parameter type to borrow instead."* You have also been using the answer since lesson [1.6](@/chapter-1/reading-input.md): every `read_line(&mut name)` you've ever written lends `name` to a function that modifies it and *gives it back automatically*, no tuple, no re-binding. That `&` is a **reference**, the act is **borrowing**, and chapter 9 is where it finally earns its name. This lesson's dance exists so you'll know exactly what references are saving you from.
{% callout(kind="best", title="Best practice") %}
Parameters: take `&str` when the function only reads the text; take `String` only when it genuinely keeps ownership. Returns: handing a newly built `String` to the caller is exactly right (that's `read_name`, `format!`, and friends). The give-and-take-back tuple is a teaching device; in real code, chapter 9's references do this job.
{% end %}
## An old debt: the consuming +
One last IOU, from lesson [5.3](@/chapter-5/introduction-to-string.md): "`+` *consumes* the `String` on its left side, which stops compiling in ways we can't explain until chapter 8 puts ownership on the table."
The table is set. Concatenation with `+` is, under the hood, a function call, and its left operand is a `String` parameter: *it takes ownership*. The right side is only lent (that `&` again). So:
```rust
fn main() {
let first = String::from("Ada");
let last = String::from("Lovelace");
let full = first + " " + &last;
println!("{full}");
println!("{last}");
}
```
```
Ada Lovelace
Lovelace
```
`last` survives: it was only viewed. `first` is gone: it was *given* to the `+`, exactly like `order` was given to `submit`, and adding `println!("{first}")` would produce the same `E0382` you can now read in your sleep. (Why design `+` to consume? Because owning the left side lets it grow that existing heap block and hand it onward, instead of copying all the text into a new one.) Chapter 5's advice stands with reasons attached: `push_str` modifies what you keep, `format!` borrows everything and consumes nothing (lesson [5.5](@/chapter-5/formatting-strings.md)), and `+` is fine when you're done with the left side.
## Quiz time
**Question #1**
Compile or not? One sentence of why.
```rust
fn shout(line: String) {
println!("{line}!!!");
}
fn main() {
let cheer = String::from("goal");
shout(cheer);
shout(cheer);
}
```
Show solution
`error[E0382]: use of moved value: `cheer``. The first call moves the value into `line`, which drops it when `shout` returns; the second call tries to move a value that no longer exists. (Fixes, in chapter order: build a second `String`, clone for the first call, or wait one chapter and lend it twice.)
**Question #2**
Without references (chapter 9 is still off-limits), fix this program so it compiles and prints both lines, keeping `describe`'s ability to read the text:
```rust
fn describe(text: String) -> usize {
text.len()
}
fn main() {
let motto = String::from("fearless");
let n = describe(motto);
println!("{motto}: {n} bytes");
}
```
Show solution
Make `describe` give the value back alongside its answer:
```rust
fn describe(text: String) -> (String, usize) {
let n = text.len();
(text, n)
}
fn main() {
let motto = String::from("fearless");
let (motto, n) = describe(motto);
println!("{motto}: {n} bytes");
}
```
```
fearless: 8 bytes
```
The tuple return moves ownership back out, and the shadowing `let (motto, n)` receives it. Feel the friction; it's the lesson. (A `.clone()` at the call site also works at the cost of duplicating the text, and chapter 9 deletes the whole problem.)
**Question #3**
For each function, pick the parameter type, `String` or `&str`, and justify it in ownership words: a) `fn print_banner(title: ???)` which decorates and prints the title; b) `fn archive(entry: ???)` which stores the text in a long-lived archive; c) `fn first_word(sentence: ???) -> ???` which returns the word before the first space.
Show solution
a) `&str`: the function only reads; it has no business taking ownership it doesn't need. b) `String`: the archive *keeps* the text, so taking ownership is honest, and the move at the call site documents the handoff. c) Takes `&str`, and (with this chapter's tools) returns a new `String` built from the word: the function reads its input and gives the caller ownership of a fresh value. (Chapter 9 will offer a better return type: a view into the original sentence.)
One tool remains in the chapter: the compiler has suggested `.clone()` at you twice now. Next lesson it gets a fair hearing, including when it's the right call and when it's a crutch.