diff --git a/src/expressions.md b/src/expressions.md index 96d2d2162..e70c71fd7 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -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 @@ -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 diff --git a/src/items.md b/src/items.md index 6865f4f46..a79696021 100644 --- a/src/items.md +++ b/src/items.md @@ -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 diff --git a/src/types.md b/src/types.md index 45c48e53f..814863ccc 100644 --- a/src/types.md +++ b/src/types.md @@ -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::}` 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() { } +let x = &mut foo::; +*x = foo::; //~ 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() { } + +// `foo_ptr_1` has function pointer type `fn()` here +let foo_ptr_1: fn() = foo::; + +// ... and so does `foo_ptr_2` - this type-checks. +let foo_ptr_2 = if want_i32 { + foo:: +} else { + foo:: +}; +``` + +## 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: @@ -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