Passing Objects

One of the things that's "hard" about Rust when you first start learning it are the different ways you can pass an object to a function or return one, and the types associated with them.

For example, Strings come in a few different flavors, and you need to know which one to use to return them.:


fn main() {
// This works:
fn return_string() -> String {
    let not_global = "I return ok, because I'm not global.".to_string();
    not_global  // Funky Rust return syntax.

// This doesn't, uncomment to see the error
fn return_broken() -> String {
    let broken = "Not OK -- I'm a global literal!";

println!("{}", return_string());

Mutable methods vs immutable methods

Before learning about passing objects, we need to create a basic "object" and test it, which has mutable and immutable methods.

pub struct Person {
    name: String,
    state: String,

impl Person {
    // See
    pub fn new(name: String, state: String) -> Self {
        Self {
            name: name,
            state: state

    pub fn print(&self) {
        println!("{} lives in {}.",, self.state);
    // Note it's &mut, not mut&
    pub fn move_to(&mut self, state: String) {
        self.state = state;

fn main() {
    let static_john = Person::new("John Lockwood".to_string(), "California".to_string());

    // Static John can't move! Next line is an error
    // static_john.move_to("North Carolina".to_string());

    // Mutable John can
    let mut john = Person::new("John Lockwood".to_string(), "California".to_string());


    john.move_to("North Carolina".to_string());

Passing Objects

Basically there are about four ways things can get passed around:

  • Directly non-mutable
  • Directly mutable
  • By reference non-mutable
  • By reference mutable

Passing objects directly

This MOVES the object to a new owner. If you do this, you can't use the reference any more. I.e. Can do it mutably or not.

fn pass_ownership_non_mutable(person: Person) {

fn pass_ownership_mutably(mut person: Person) {
    person.move_to("New York".to_string());


    // Pass a person not by reference
    let john2 = Person::new("John".to_string(), "California".to_string());
    // Can't do -- borrowed after move:  E0382:
    // john2.print();

    // Note we don't need to declare this as mut here
    // for that it matches the function signature of pass_ownership_mutually
    let john3 = Person::new("John ".to_string(), "California".to_string());
    // Can't do -- borrowed after move:  E0382:
    // john3.print();

Passing by reference

fn pass_reference_non_mutable(person: &Person) {

fn pass_reference_mutably(person: &mut Person) {


    let mut john3 = Person::new("John ".to_string(), "California".to_string());
    pass_reference_mutably(&mut john3);

    // Reusing, ownership not transfered!