Skip to content

Commit 2b29a56

Browse files
authored
Merge pull request #652 from gnzlbg/extern_fn_definition
Correct errors in the reference of extern functions definitions and declarations
2 parents d191a0c + c4ef0ee commit 2b29a56

File tree

4 files changed

+68
-28
lines changed

4 files changed

+68
-28
lines changed

src/abi.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub fn name_in_rust() { }
8888
[_MetaNameValueStr_]: attributes.md#meta-item-attribute-syntax
8989
[`static` items]: items/static-items.md
9090
[attribute]: attributes.md
91-
[extern functions]: items/functions.md#extern-functions
91+
[extern functions]: items/functions.md#extern-function-qualifier
9292
[external blocks]: items/external-blocks.md
9393
[function]: items/functions.md
9494
[item]: items.md

src/items/external-blocks.md

+11-10
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,13 @@
2929
> _NamedFunctionParametersWithVariadics_ :\
3030
> &nbsp;&nbsp; ( _NamedFunctionParam_ `,` )<sup>\*</sup> _NamedFunctionParam_ `,` `...`
3131
32-
External blocks form the basis for Rust's foreign function interface.
33-
Declarations in an external block describe symbols in external, non-Rust
34-
libraries.
32+
External blocks provide _declarations_ of items that are not _defined_ in the
33+
current crate and are the basis of Rust's foreign function interface. These are
34+
akin to unchecked imports.
35+
36+
Two kind of item _declarations_ are allowed in external blocks: [functions] and
37+
[statics]. Calling functions or accessing statics that are declared in external
38+
blocks is only allowed in an `unsafe` context.
3539

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

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

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

88-
Finally, there are some rustc-specific ABI strings:
89-
90-
* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics.
91-
* `extern "rust-call"` -- The ABI of the Fn::call trait functions.
92-
* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for
93-
example, `sqrt` -- have this ABI. You should never have to deal with it.
94-
9594
## Variadic functions
9695

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

166165
[IDENTIFIER]: ../identifiers.md
167166
[WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html
167+
[functions]: functions.md
168+
[statics]: static-items.md
168169
[_Abi_]: functions.md
169170
[_FunctionReturnType_]: functions.md
170171
[_Generics_]: generics.md

src/items/functions.md

+55-16
Original file line numberDiff line numberDiff line change
@@ -107,35 +107,73 @@ component after the function name. This might be necessary if there is not
107107
sufficient context to determine the type parameters. For example,
108108
`mem::size_of::<u32>() == 4`.
109109

110-
## Extern functions
110+
## Extern function qualifier
111111

112-
Extern functions are part of Rust's foreign function interface, providing the
113-
opposite functionality to [external blocks]. Whereas external
114-
blocks allow Rust code to call foreign code, extern functions with bodies
115-
defined in Rust code _can be called by foreign code_. They are defined in the
116-
same way as any other Rust function, except that they have the `extern`
117-
qualifier.
112+
The `extern` function qualifier allows providing function _definitions_ that can
113+
be called with a particular ABI:
114+
115+
```rust,ignore
116+
extern "ABI" fn foo() { ... }
117+
```
118+
119+
These are often used in combination with [external block] items which provide
120+
function _declarations_ that can be used to call functions without providing
121+
their _definition_:
122+
123+
```rust,ignore
124+
extern "ABI" {
125+
fn foo(); /* no body */
126+
}
127+
unsafe { foo() }
128+
```
129+
130+
When `"extern" Abi?*` is omitted from `FunctionQualifiers` in function items,
131+
the ABI `"Rust"` is assigned. For example:
118132

119133
```rust
120-
// Declares an extern fn, the ABI defaults to "C"
121-
extern fn new_i32() -> i32 { 0 }
134+
fn foo() {}
135+
```
136+
137+
is equivalent to:
122138

123-
// Declares an extern fn with "stdcall" ABI
139+
```rust
140+
extern "Rust" fn foo() {}
141+
```
142+
143+
Functions in Rust can be called by foreign code, and using an ABI that
144+
differs from Rust allows, for example, to provide functions that can be
145+
called from other programming languages like C:
146+
147+
```rust
148+
// Declares a function with the "C" ABI
149+
extern "C" fn new_i32() -> i32 { 0 }
150+
151+
// Declares a function with the "stdcall" ABI
124152
# #[cfg(target_arch = "x86_64")]
125153
extern "stdcall" fn new_i32_stdcall() -> i32 { 0 }
126154
```
127155

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

131159
```rust
132-
# extern fn new_i32() -> i32 { 0 }
160+
extern fn new_i32() -> i32 { 0 }
161+
let fptr: extern fn() -> i32 = new_i32;
162+
```
163+
164+
is equivalent to:
165+
166+
```rust
167+
extern "C" fn new_i32() -> i32 { 0 }
133168
let fptr: extern "C" fn() -> i32 = new_i32;
134169
```
135170

136-
As non-Rust calling conventions do not support unwinding, unwinding past the end
137-
of an extern function will cause the process to abort. In LLVM, this is
138-
implemented by executing an illegal instruction.
171+
Functions with an ABI that differs from `"Rust"` do not support unwinding in the
172+
exact same way that Rust does. Therefore, unwinding past the end of functions
173+
with such ABIs causes the process to abort.
174+
175+
> **Note**: The LLVM backend of the `rustc` implementation
176+
aborts the process by executing an illegal instruction.
139177

140178
## Const functions
141179

@@ -243,3 +281,4 @@ attributes macros.
243281
[`export_name`]: ../abi.md#the-export_name-attribute
244282
[`link_section`]: ../abi.md#the-link_section-attribute
245283
[`no_mangle`]: ../abi.md#the-no_mangle-attribute
284+
[external_block_abi]: external-blocks.md#abi

src/types/function-pointer.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ x = bo(5,7);
5151
[_Type_]: ../types.md#type-expressions
5252
[`extern`]: ../items/external-blocks.md
5353
[closures]: closure.md
54-
[extern function]: ../items/functions.md#extern-functions
54+
[extern function]: ../items/functions.md#extern-function-qualifier
5555
[function items]: function-item.md
5656
[unsafe function]: ../unsafe-functions.md

0 commit comments

Comments
 (0)