# Input to functions and methods

### Let the client decide when to copy and where to place data. [FIXME: needs RFC]

#### Copying:

Prefer

fn main() { fn foo(b: Bar) { // use b as owned, directly } }

    fn foo(b: Bar) {
       // use b as owned, directly
    }

over

fn main() { fn foo(b: &Bar) { let b = b.clone(); // use b as owned after cloning } }

    fn foo(b: &Bar) {
        let b = b.clone();
        // use b as owned after cloning
    }

If a function requires ownership of a value of unknown type `T`, but does not otherwise need to make copies, the function should take ownership of the argument (pass by value `T`) rather than using `.clone()`. That way, the caller can decide whether to relinquish ownership or to `clone`.

Similarly, the `Copy` trait bound should only be demanded it when absolutely needed, not as a way of signaling that copies should be cheap to make.

#### Placement:

Prefer

fn main() { fn foo(b: Bar) -> Bar { ... } }

    fn foo(b: Bar) -> Bar { ... }

over

fn main() { fn foo(b: Box<Bar>) -> Box<Bar> { ... } }

    fn foo(b: Box<Bar>) -> Box<Bar> { ... }

for concrete types `Bar` (as opposed to trait objects). This way, the caller can decide whether to place data on the stack or heap. No overhead is imposed by letting the caller determine the placement.

### Minimize assumptions about parameters. [FIXME: needs RFC]

The fewer assumptions a function makes about its inputs, the more widely usable it becomes.

#### Minimizing assumptions through generics:

Prefer

fn main() { fn foo<T: Iterator<i32>>(c: T) { ... } }

    fn foo<T: Iterator<i32>>(c: T) { ... }

over any of

fn main() { fn foo(c: &[i32]) { ... } fn foo(c: &Vec<i32>) { ... } fn foo(c: &SomeOtherCollection<i32>) { ... } }

    fn foo(c: &[i32]) { ... }
    fn foo(c: &Vec<i32>) { ... }
    fn foo(c: &SomeOtherCollection<i32>) { ... }

if the function only needs to iterate over the data.

More generally, consider using generics to pinpoint the assumptions a function needs to make about its arguments.

On the other hand, generics can make it more difficult to read and understand a function's signature. Aim for "natural" parameter types that a neither overly concrete nor overly abstract. See the discussion on traits for more guidance.

#### Minimizing ownership assumptions:

Prefer either of

fn main() { fn foo(b: &Bar) { ... } fn foo(b: &mut Bar) { ... } }

    fn foo(b: &Bar) { ... }
    fn foo(b: &mut Bar) { ... }

over

fn main() { fn foo(b: Bar) { ... } }

    fn foo(b: Bar) { ... }

That is, prefer borrowing arguments rather than transferring ownership, unless ownership is actually needed.

### Prefer compound return types to out-parameters. [FIXME: needs RFC]

Prefer

fn main() { fn foo() -> (Bar, Bar) }

    fn foo() -> (Bar, Bar)

over

fn main() { fn foo(output: &mut Bar) -> Bar }

    fn foo(output: &mut Bar) -> Bar

for returning multiple `Bar` values.

Compound return types like tuples and structs are efficiently compiled and do not require heap allocation. If a function needs to return multiple values, it should do so via one of these types.

The primary exception: sometimes a function is meant to modify data that the caller already owns, for example to re-use a buffer:

fn main() { fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> }

    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>

(From the Read trait.)

### Consider validating arguments, statically or dynamically. [FIXME: needs RFC]

Note: this material is closely related to library-level guarantees.

Rust APIs do not generally follow the robustness principle: "be conservative in what you send; be liberal in what you accept".

Instead, Rust code should enforce the validity of input whenever practical.

Enforcement can be achieved through the following mechanisms (listed in order of preference).

#### Static enforcement:

Choose an argument type that rules out bad inputs.

For example, prefer

fn main() { enum FooMode { Mode1, Mode2, Mode3, } fn foo(mode: FooMode) { ... } }

    enum FooMode {
        Mode1,
        Mode2,
        Mode3,
    }
    fn foo(mode: FooMode) { ... }

over

fn main() { fn foo(mode2: bool, mode3: bool) { assert!(!mode2 || !mode3); ... } }

    fn foo(mode2: bool, mode3: bool) {
        assert!(!mode2 || !mode3);
        ...
    }

Static enforcement usually comes at little run-time cost: it pushes the costs to the boundaries. It also catches bugs early, during compilation, rather than through run-time failures.

On the other hand, some properties are difficult or impossible to express using types.

#### Dynamic enforcement:

Validate the input as it is processed (or ahead of time, if necessary). Dynamic checking is often easier to implement than static checking, but has several downsides:

1. Runtime overhead (unless checking can be done as part of processing the input).
2. Delayed detection of bugs.
3. Introduces failure cases, either via `panic!` or `Result`/`Option` types (see the error handling guidelines), which must then be dealt with by client code.

#### Dynamic enforcement with `debug_assert!`:

Same as dynamic enforcement, but with the possibility of easily turning off expensive checks for production builds.

#### Dynamic enforcement with opt-out:

Same as dynamic enforcement, but adds sibling functions that opt out of the checking.

The convention is to mark these opt-out functions with a suffix like `_unchecked` or by placing them in a `raw` submodule.

The unchecked functions can be used judiciously in cases where (1) performance dictates avoiding checks and (2) the client is otherwise confident that the inputs are valid.

> [FIXME] Should opt-out functions be marked `unsafe`?