An object with an immutable type is passed around (both in assignment statements and in function calls) by copying, whereas a mutable type is passed around by reference.
Or put another way: the semantics of argument passing is always by reference. The implementation may be anything as long as it implements reference semantics. For immutables, there’s no way to tell the difference between passing by reference or value, so the compiler is free to choose between them as it sees fit and since passing by value is often the most efficient, that’s generally what it does.
Having it written like that seems slightly confusing. I think it is better that one thinks of all objects being passed exactly in the same way, no matter their mutability, (and then the compiler can of course optimize things behind your back).
Writing it out like that seems to get things the wrong way around. It is the copying that is the optimisation, not the passing by reference.
An object with an immutable type is passed around (both in assignment statements and in function calls) by copying, whereas a mutable type is passed around by reference.
Most responders have commented on the second statement, but I’d like to point out also that the first statement “all arguments to functions are passed by reference” is also potentially misleading. In C++, passing by reference as in void swapint(int& a, int& b) means that the routine can modify scalar variables in its caller: swapint(u,v) changes the caller’s values of u and v. This is not possible in Julia because in Julia, every assignment statement rebinds a variable “from scratch”. However, a Julia newcomer with a C/C++ background and not familiar with Julia’s concept of binding objects to variable names is likely to be confused by the statement “all arguments to functions are passed by reference”.