Skip to content
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

Correct errors in the reference of extern functions definitions and declarations #652

Merged
merged 15 commits into from
Aug 22, 2019
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
2 changes: 1 addition & 1 deletion src/abi.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub fn name_in_rust() { }
[_MetaNameValueStr_]: attributes.md#meta-item-attribute-syntax
[`static` items]: items/static-items.md
[attribute]: attributes.md
[extern functions]: items/functions.md#extern-functions
[extern functions]: items/functions.md#extern-function-qualifier
[external blocks]: items/external-blocks.md
[function]: items/functions.md
[item]: items.md
Expand Down
21 changes: 11 additions & 10 deletions src/items/external-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@
> _NamedFunctionParametersWithVariadics_ :\
> &nbsp;&nbsp; ( _NamedFunctionParam_ `,` )<sup>\*</sup> _NamedFunctionParam_ `,` `...`

External blocks form the basis for Rust's foreign function interface.
Declarations in an external block describe symbols in external, non-Rust
libraries.
External blocks provide _declarations_ of items that are not _defined_ in the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be more explicit that these are "imports" of a sort.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to clarify that.

current crate and are the basis of Rust's foreign function interface. These are
akin to unchecked imports.

Two kind of item _declarations_ are allowed in external blocks: [functions] and
[statics]. Calling functions or accessing statics that are declared in external
blocks is only allowed in an `unsafe` context.

Functions within external blocks are declared in the same way as other Rust
functions, with the exception that they may not have a body and are instead
Expand All @@ -48,6 +52,8 @@ extern "abi" for<'l1, ..., 'lm> fn(A1, ..., An) -> R`, where `'l1`, ... `'lm`
are its lifetime parameters, `A1`, ..., `An` are the declared types of its
parameters and `R` is the declared return type.

Statics within external blocks are declared in the same way as statics outside of external blocks,
except that they do not have an expression initializing their value.
It is `unsafe` to access a static item declared in an extern block, whether or
not it's mutable.

Expand Down Expand Up @@ -85,13 +91,6 @@ There are also some platform-specific ABI strings:
* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's
`__vectorcall` and clang's `__attribute__((vectorcall))`

Finally, there are some rustc-specific ABI strings:

* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics.
* `extern "rust-call"` -- The ABI of the Fn::call trait functions.
* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for
example, `sqrt` -- have this ABI. You should never have to deal with it.

## Variadic functions

Functions within external blocks may be variadic by specifying `...` after one
Expand Down Expand Up @@ -165,6 +164,8 @@ extern {

[IDENTIFIER]: ../identifiers.md
[WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html
[functions]: functions.md
[statics]: static-items.md
[_Abi_]: functions.md
[_FunctionReturnType_]: functions.md
[_Generics_]: generics.md
Expand Down
71 changes: 55 additions & 16 deletions src/items/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,35 +107,73 @@ component after the function name. This might be necessary if there is not
sufficient context to determine the type parameters. For example,
`mem::size_of::<u32>() == 4`.

## Extern functions
## Extern function qualifier

Extern functions are part of Rust's foreign function interface, providing the
opposite functionality to [external blocks]. Whereas external
blocks allow Rust code to call foreign code, extern functions with bodies
defined in Rust code _can be called by foreign code_. They are defined in the
same way as any other Rust function, except that they have the `extern`
qualifier.
The `extern` function qualifier allows providing function _definitions_ that can
be called with a particular ABI:
gnzlbg marked this conversation as resolved.
Show resolved Hide resolved

```rust,ignore
extern "ABI" fn foo() { ... }
gnzlbg marked this conversation as resolved.
Show resolved Hide resolved
```

These are often used in combination with [external block] items which provide
function _declarations_ that can be used to call functions without providing
their _definition_:

```rust,ignore
extern "ABI" {
fn foo(); /* no body */
}
unsafe { foo() }
```

When `"extern" Abi?*` is omitted from `FunctionQualifiers` in function items,
the ABI `"Rust"` is assigned. For example:

```rust
// Declares an extern fn, the ABI defaults to "C"
extern fn new_i32() -> i32 { 0 }
fn foo() {}
```

is equivalent to:

// Declares an extern fn with "stdcall" ABI
```rust
extern "Rust" fn foo() {}
```

Functions in Rust can be called by foreign code, and using an ABI that
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a run-on sentence, or at least feels like one. Also, "Rust's functions". And what does "foreign code" here mean differently than code from other programming languages?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust code exposed with a C ABI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to improve this.

differs from Rust allows, for example, to provide functions that can be
called from other programming languages like C:

```rust
// Declares a function with the "C" ABI
extern "C" fn new_i32() -> i32 { 0 }

// Declares a function with the "stdcall" ABI
# #[cfg(target_arch = "x86_64")]
extern "stdcall" fn new_i32_stdcall() -> i32 { 0 }
```

Unlike normal functions, extern fns have type `extern "ABI" fn()`. This is the
same type as the functions declared in an extern block.
Just as with [external block], when the `extern` keyword is used and the `"ABI`
is omitted, the ABI used defaults to `"C"`. That is, this:

```rust
# extern fn new_i32() -> i32 { 0 }
extern fn new_i32() -> i32 { 0 }
let fptr: extern fn() -> i32 = new_i32;
```

is equivalent to:

```rust
extern "C" fn new_i32() -> i32 { 0 }
let fptr: extern "C" fn() -> i32 = new_i32;
```

As non-Rust calling conventions do not support unwinding, unwinding past the end
of an extern function will cause the process to abort. In LLVM, this is
implemented by executing an illegal instruction.
Functions with an ABI that differs from `"Rust"` do not support unwinding in the
exact same way that Rust does. Therefore, unwinding past the end of functions
with such ABIs causes the process to abort.

> **Note**: The LLVM backend of the `rustc` implementation
aborts the process by executing an illegal instruction.

## Const functions

Expand Down Expand Up @@ -243,3 +281,4 @@ attributes macros.
[`export_name`]: ../abi.md#the-export_name-attribute
[`link_section`]: ../abi.md#the-link_section-attribute
[`no_mangle`]: ../abi.md#the-no_mangle-attribute
[external_block_abi]: external-blocks.md#abi
2 changes: 1 addition & 1 deletion src/types/function-pointer.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ x = bo(5,7);
[_Type_]: ../types.md#type-expressions
[`extern`]: ../items/external-blocks.md
[closures]: closure.md
[extern function]: ../items/functions.md#extern-functions
[extern function]: ../items/functions.md#extern-function-qualifier
[function items]: function-item.md
[unsafe function]: ../unsafe-functions.md