Skip to content

modernize the function sections in the reference #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ assert_eq!(unit_x.0, 1.0);
A _call expression_ consists of an expression followed by a parenthesized
expression-list. It invokes a function, providing zero or more input variables.
If the function eventually returns, then the expression completes. For
[non-function types](types.html#function-types), the expression f(...) uses the
[non-function types](types.html#function-item-types), the expression f(...) uses the
method on one of the `std::ops::Fn`, `std::ops::FnMut` or `std::ops::FnOnce`
traits, which differ in whether they take the type by reference, mutable
reference, or take ownership respectively. An automatic borrow will be taken if
Expand Down Expand Up @@ -962,7 +962,7 @@ well as the following additional casts. Here `*T` means either `*const T` or
| `*T` where `T: Sized` | Numeric type | Pointer to address cast |
| Integer type | `*V` where `V: Sized` | Address to pointer cast |
| `&[T; n]` | `*const T` | Array to pointer cast |
| [Function pointer](types.html#function-types) | `*V` where `V: Sized` | Function pointer to pointer cast |
| [Function pointer](types.html#function-pointer-types) | `*V` where `V: Sized` | Function pointer to pointer cast |
| Function pointer | Integer | Function pointer to address cast |

\* or `T` and `V` are compatible unsized types, e.g., both slices, both the
Expand Down
44 changes: 25 additions & 19 deletions src/items.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,46 +270,52 @@ fn main() {}

## Functions

A _function item_ defines a sequence of [statements] and a
final [expression], along with a name and a set of
A _function_ consists of a [block], along with a name and a set of
parameters. Other than a name, all these are optional.
Functions are declared with the keyword `fn`. Functions may declare a
set of *input* [*variables*][variables] as parameters, through which the caller
passes arguments into the function, and the *output* [*type*][type]
of the value the function will return to its caller on completion.

[statements]: statements.html
[expression]: expressions.html
[block]: expressions.html#block-expressions
[variables]: variables.html
[type]: types.html

A function may also be copied into a first-class *value*, in which case the
value has the corresponding [*function type*][function type], and can be used
otherwise exactly as a function item (with a minor additional cost of calling
the function indirectly).
When referred to, a _function_ yields a first-class *value* of the
corresponding zero-sized [*function item type*][function item type], which
when called evaluates to a direct call to the function.

[function type]: types.html#function-types

Every control path in a function logically ends with a `return` expression or a
diverging expression. If the outermost block of a function has a
value-producing expression in its final-expression position, that expression is
interpreted as an implicit `return` expression applied to the final-expression.

An example of a function:
[function item type]: types.html#function-item-types

For example, this is a simple function:
```rust
fn add(x: i32, y: i32) -> i32 {
x + y
fn answer_to_life_the_universe_and_everything() -> i32 {
return 42;
}
```

As with `let` bindings, function arguments are irrefutable patterns, so any
pattern that is valid in a let binding is also valid as an argument.
pattern that is valid in a let binding is also valid as an argument:

```rust
fn first((value, _): (i32, i32)) -> i32 { value }
```

The block of a function is conceptually wrapped in a block that binds the
argument patterns and then `return`s the value of the function's block. This
means that the tail expression of the block, if evaluated, ends up being
returned to the caller. As usual, an explicit return expression within
the body of the function will short-cut that implicit return, if reached.

For example, the function above behaves as if it was written as:

```rust,ignore
// argument_0 is the actual first argument passed from the caller
let (value, _) = argument_0;
return {
value
};
```

### Generic functions

Expand Down
75 changes: 55 additions & 20 deletions src/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,62 @@ varieties of pointer in Rust:
The standard library contains additional 'smart pointer' types beyond references
and raw pointers.

## Function types
## Function item types

The function type constructor `fn` forms new function types. A function 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.
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.

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::<u32>}` 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
fn foo<T>() { }
let x = &mut foo::<i32>;
*x = foo::<u32>; //~ 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`:

[coercion]: type-coercions.html

```rust
# let want_i32 = false;
# fn foo<T>() { }

// `foo_ptr_1` has function pointer type `fn()` here
let foo_ptr_1: fn() = foo::<i32>;

// ... and so does `foo_ptr_2` - this type-checks.
let foo_ptr_2 = if want_i32 {
foo::<i32>
} else {
foo::<u32>
};
```

## 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).

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:

Expand All @@ -250,22 +301,6 @@ let bo: Binop = add;
x = bo(5,7);
```

### Function types for specific items

Internal to the compiler, there are also function types that are specific to a particular
function item. In the following snippet, for example, the internal types of the functions
`foo` and `bar` are different, despite the fact that they have the same signature:

```rust
fn foo() { }
fn bar() { }
```

The types of `foo` and `bar` can both be implicitly coerced to the fn
pointer type `fn()`. There is currently no syntax for unique fn types,
though the compiler will emit a type like `fn() {foo}` in error
messages to indicate "the unique fn type for the function `foo`".

## Closure types

A [closure expression](expressions.html#closure-expressions) produces a closure
Expand Down