Refactoring Commands

abstract

Usage: abstract SIG PAT [BODY]

Replace all instances of pat with calls to a new function whose name and signature is given by sig. Example:

Input:

 1 + 2

After running abstract 'add(x: u32, y: u32) -> u32' 'x + y':

 add(1, 2)

 // Elsewhere:
 fn add(x: u32, y: u32) -> u32 { x + y }

All type and value parameter names in sig act as bindings when matching pat. The captured exprs and types are passed as parameters when building the new call expression. The body of the function is body, if provided, otherwise pat itself.

Non-ident patterns in sig are not supported. It is also an error for any type parameter's name to collide with any value parameter.

If matching with pat fails to capture expressions for any of the value parameters of sig, it is an error. If it fails to capture for a type parameter, the parameter is filled in with _ (infer).

autoretype

Usage: autoretype 'A: T'...

Marks: A... (specified in command)

Change the type of nodes with mark A to the new type T, propagating changes and inserting casts when possible to satisfy type checking. Multiple simultaneous retypings can be specified in this command as separate arguments. Each argument should be of the form: label: type where label is a mark label and type can be parsed as a valid rust type.

bitcast_retype

Usage: bitcast_retype PAT REPL

Marks: may read marks depending on PAT

For every type in the crate matching PAT, change the type to REPL. PAT and REPL are types, and can use placeholders in the manner of rewrite_ty. For each definitions whose type has changed, it also inserts mem::transmute calls at each use of the definition to fix discrepancies between the old and new types. (This implies that the original type and its replacement must be transmutable to each other.)

bytestr_to_str

Usage: bytestr_to_str

Marks: target

Convert bytestring literal expressions marked target to string literal expressions.

Note the mark must be placed on the expression, as it is currently difficult to mark a literal node.

canonicalize_externs

Usage: canonicalize_externs MOD_PATH

Marks: target

Replace foreign items ("externs") with references to externs in a different crate or module.

For each foreign fn or static marked target, if a foreign item with the same symbol exists in the module at MOD_PATH (which can be part of an external crate), it deletes the marked foreign item and replaces all its uses with uses of the matching foreign item in MOD_PATH. If a replacement item has a different type than the original, it also inserts the necessary casts at each use of the item.

canonicalize_structs

Usage: canonicalize_structs

Marks: target

For each type definition marked target, delete all other type definitions with the same name, and replace their uses with uses of the target type.

This only works when all the identically-named types have the same definition, such as when all are generated from #includes of the same C header.

Example:

 mod a {
     pub struct Foo { ... }  // Foo: target
 }

 mod b {
     struct Foo { ... }  // same as ::a::Foo

     unsafe fn use_foo(x: &Foo) { ... }
 }

After running canonicalize_structs:

 mod a {
     pub struct Foo { ... }
 }

 mod b {
     // 1. `struct Foo` has been deleted
     // 2. `use_foo` now references `::a::Foo` directly
     unsafe fn use_foo(x: &::a::Foo) { ... }
 }

Note that this transform does not check or adjust item visibility. If the target type is not visible throughout the crate, this may introduce compile errors.

char_literals

Obsolete - the translator now does this automatically.

Usage: char_literals

Replace integer literals cast to libc::c_char with actual char literals. For example, replaces 65 as libc::c_char with 'A' as libc::c_char.

clear_marks

Usage: clear_marks

Marks: clears all marks

Remove all marks from all nodes.

commit

Usage: commit

Write the current crate to disk (by rewriting the original source files), then read it back in, clearing all mark. This can be useful as a "checkpoint" between two sets of transformations, if applying both sets of changes at once proves to be too much for the rewriter.

This is only useful when the rewrite mode is inplace. Otherwise the "write" part of the operation won't actually change the original source files, and the "read" part will revert the crate to its original form.

convert_cast_as_ptr

convert_format_args

Usage: convert_format_args

Marks: target

For each function call, if one of its argument expressions is marked target, then parse that argument as a printf format string, with the subsequent arguments as the format args. Replace both the format string and the args with an invocation of the Rust format_args! macro.

This transformation applies casts to the remaining arguments to account for differences in argument conversion behavior between C-style and Rust-style string formatting. However, it does not attempt to convert the format_args! output into something compatible with the original C function. This results in a type error, so this pass should usually be followed up by an additional rewrite to change the function being called.

Example:

 printf("hello %d\n", 123);

If the string "hello %d\n" is marked target, then running convert_format_string will replace this call with

 printf(format_args!("hello {:}\n", 123 as i32));

At this point, it would be wise to replace the printf expression with a function that accepts the std::fmt::Arguments produced by format_args!.

convert_printfs

copy_marks

Usage: copy_marks OLD_MARK NEW_MARK

Marks: reads OLD_MARK; sets NEW_MARK

For every node bearing OLD_MARK, also apply NEW_MARK.

create_item

Usage: create_item ITEMS <inside/after> [MARK]

Marks: MARK/target

Parse ITEMS as item definitions, and insert the parsed items either inside (as the first child) or after (as a sibling) of the AST node bearing MARK (default: target). Supports adding items to both mods and blocks.

Note that other itemlikes, such as impl and trait items, are not handled by this command.

delete_items

Usage: delete_items

Marks: target

Delete all items marked target from the AST. This handles items in both mods and blocks, but doesn't handle other itemlikes.

delete_marks

Usage: delete_marks MARK

Marks: clears MARK

Remove MARK from every node where it appears.

fix_unused_unsafe

Usage: fix_unused_unsafe

Find unused unsafe blocks and turn them into ordinary blocks.

fold_let_assign

Usage: fold_let_assign

Fold together lets with no initializer or a trivial one, and subsequent assignments. For example, replace let x; x = 10; with let x = 10;.

func_to_method

Usage: func_to_method

Marks: target, dest

Turn functions marked target into static methods (no self) in the impl block marked dest. Turn functions that have an argument marked target into methods, replacing the named argument with self. Rewrite all uses of marked functions to call the new method versions.

Marked arguments of type T, &T, and &mut T (where T is the Self type of the dest impl) will be converted to self, &self, and &mut self respectively.

generalize_items

Usage: generalize_items VAR [TY]

Marks: target

Replace marked types with generic type parameters.

Specifically: add a new type parameter called VAR to each item marked target, replacing type annotations inside that item that are marked target with uses of the type parameter. Also update all uses of target items, passing TY as the new type argument when used inside a non-target item, and passing the type variable VAR when used inside a target item.

If TY is not provided, it defaults to a copy of the first type annotation that was replaced with VAR.

Example:

 struct Foo {    // Foo: target
     x: i32,     // i32: target
     y: i32,
 }

 fn f(foo: Foo) { ... }  // f: target

 fn main() {
     f(...);
 }

After running generalize_items T:

 // 1. Foo gains a new type parameter `T`
 struct Foo<T> {
     // 2. Marked type annotations become `T`
     x: T,
     y: i32,
 }

 // 3. `f` gains a new type parameter `T`, and passes
 // it through to uses of `Foo`
 fn f<T>(foo: Foo<T>) { ... }
 struct Bar<T> {
     foo: Foo<T>,
 }

 fn main() {
     // 4. Uses outside target items use `i32`, the
     // first type that was replaced with `T`.
     f::<i32>(...);
 }

ionize

Usage: ionize

Marks: target

Convert each union marked target to a type-safe Rust enum. The generated enums will have as_variant and as_variant_mut methods for each union field, which panic if the enum is not the named variant. Also updates assignments to union variables to assign one of the new enum variants, and updates uses of union fields to call the new methods instead.

let_x_uninitialized

Obsolete - the translator now does this automatically.

Usage: let_x_uninitialized

For each local variable that is uninitialized (let x;), add mem::uninitialized() as an initializer expression.

link_funcs

Usage: link_funcs

Link up function declarations and definitions with matching symbols across modules. For every foreign fn whose symbol matches a fn definition elsewhere in the program, it replaces all uses of the foreign fn with a direct call of the fn definition, and deletes the foreign fn.

Example:

 mod a {
     #[no_mangle]
     unsafe extern "C" fn foo() { ... }
 }

 mod b {
     extern "C" {
         // This resolves to `a::foo` during linking.
         fn foo();
     }

     unsafe fn use_foo() {
         foo();
     }
 }

After running link_funcs:

 mod a {
     #[no_mangle]
     unsafe extern "C" fn foo() { ... }
 }

 mod b {
     // 1. Foreign fn `foo` has been deleted
     unsafe fn use_foo() {
         // 2. `use_foo` now calls `foo` directly
         ::a::foo();
     }
 }

link_incomplete_types

Usage: link_incomplete_types

Link up type declarations and definitions with matching names across modules. For every foreign type whose name matches a type definition elsewhere in the program, it replaces all uses of the foreign type with the type definition, and deletes the foreign type.

Example:

 mod a {
     struct Foo { ... }
 }

 mod b {
     extern "C" {
         type Foo;
     }

     unsafe fn use_foo(x: &Foo) { ... }
 }

After running link_incomplete_types:

 mod a {
     struct Foo { ... }
 }

 mod b {
     // 1. Foreign fn `Foo` has been deleted
     // 2. `use_foo` now references `Foo` directly
     unsafe fn use_foo(x: &::a::Foo) { ... }
 }

mark_arg_uses

Usage: mark_arg_uses ARG_IDX MARK

Marks: reads MARK; sets/clears MARK

For every fn definition bearing MARK, apply MARK to expressions passed in as argument ARG_IDX in calls to that function. Removes MARK from the original function.

mark_callers

Usage: mark_callers MARK

Marks: reads MARK; sets/clears MARK

For every fn definition bearing MARK, apply MARK to call expressions that call that function. Removes MARK from the original function.

mark_field_uses

Obsolete - use select with match_expr!(typed!(::TheStruct).field) instead

Usage: mark_field_uses FIELD MARK

Marks: reads MARK; sets/clears MARK

For every struct definition bearing MARK, apply MARK to expressions that use FIELD of that struct. Removes MARK from the original struct.

mark_pub_in_mod

Obsolete - use select instead.

Usage: mark_pub_in_mod MARK

Marks: reads MARK; sets MARK

In each mod bearing MARK, apply MARK to every public item in the module.

mark_related_types

Usage: mark_related_types [MARK]

Marks: MARK/target

For each type annotation bearing MARK (default: target), apply MARK to all other type annotations that must be the same type according to (a simplified version of) Rust's typing rules.

For example, in this code:

 fn f(x: i32, y: i32) -> i32 {
     x
 }

The i32 annotations on x and the return type of f are related, because changing these annotations to two unequal types would produce a type error. But the i32 annotation on y is unrelated, and can be changed independently of the other two.

mark_uses

Usage: mark_uses MARK

Marks: reads MARK; sets/clears MARK

For every top-level definition bearing MARK, apply MARK to uses of that definition. Removes MARK from the original definitions.

ownership_annotate

Usage: ownership_annotate [MARK]

Marks: MARK/target

Run ownership analysis on functions bearing MARK (default: target), and add attributes to each function describing its inferred ownership properties. See analysis/ownership/README.md for details on ownership inference.

ownership_mark_pointers

Usage: ownership_mark_pointers [MARK]

Marks: reads MARK/target; sets ref, mut, and box

Run ownership analysis on functions bearing MARK (default: target), then for pointer type appearing in their argument and return types, apply one of the marks ref, mut, or box, reflecting the results of the ownership analysis. See analysis/ownership/README.md for details on ownership inference.

ownership_split_variants

Usage: ownership_split_variants [MARK]

Marks: MARK/target

Run ownership analysis on functions bearing MARK (default: target), and split each ownership-polymorphic functions into multiple monomorphic variants. See analysis/ownership/README.md for details on ownership inference.

pick_node

Test command - not intended for general use.

Usage: pick_node KIND FILE LINE COL

Find a node of kind KIND at location FILE:LINE:COL. If successful, logs the node's ID and span at level info.

print_marks

Test command - not intended for general use.

Usage: print_marks

Marks: reads all

Logs the ID and label of every mark, at level info.

print_spans

Test command - not intended for general use.

Usage: print_spans

Print IDs, spans, and pretty-printed source for all exprs, pats, tys, stmts, and items.

reconstruct_for_range

Usage: reconstruct_for_range

Replaces i = start; while i < end { ...; i += step; } with for i in (start .. end).step_by(step) { ...; }.

reconstruct_while

Obsolete - the translator now does this automatically.

Usage: reconstruct_while

Replaces all instances of loop { if !cond { break; } ... } with while loops.

remove_null_terminator

Usage: remove_null_terminator

Marks: target

Remove a trailing \0 character from marked string and bytestring literal expressions.

Note the mark must be placed on the expression, as it is currently difficult to mark a literal node.

remove_redundant_casts

remove_redundant_let_types

remove_unused_labels

Usage: remove_unused_labels

Removes loop labels that are not used in a named break or continue.

rename_items_regex

Usage: rename_items_regex PAT REPL [FILTER]

Marks: reads FILTER

Replace PAT (a regular expression) with REPL in all item names. If FILTER is provided, only items bearing the FILTER mark will be renamed.

rename_marks

Usage: rename_marks OLD_MARK NEW_MARK

Marks: reads/clears OLD_MARK; sets NEW_MARK

For every node bearing OLD_MARK, remove OLD_MARK and apply NEW_MARK.

rename_struct

Obsolete - use rename_items_regex instead.

Usage: rename_struct NAME

Marks: target

Rename the struct marked target to NAME. Only supports renaming a single struct at a time.

rename_unnamed

Usage: rename_unnamed

Renames all Idents that have unnamed throughout the Crate, so the Crate can have a completely unique naming scheme for Anonymous Types. This command should be ran after transpiling using c2rust-transpile, and is also mainly to be used when doing the reorganize_definition pass; although this pass can run on any c2rust-transpiled project.

Example:

pub mod foo {
    pub struct unnamed {
        a: i32
    }
}

pub mod bar {
    pub struct unnamed {
        b: usize
    }
}

Becomes:

pub mod foo {
    pub struct unnamed {
        a: i32
    }
}

pub mod bar {
    pub struct unnamed_1 {
        b: usize
    }
}

reoganize_definitions

replace_items

Usage: replace_items

Marks: target, repl

Replace all uses of items marked target with reference to the item marked repl, then remove all target items.

retype_argument

Usage: retype_argument NEW_TY WRAP UNWRAP

Marks: target

For each argument marked target, change the type of the argument to NEW_TY, and use WRAP and UNWRAP to convert values to and from the original type of the argument at call sites and within the function body.

WRAP should contain an expression placeholder __old, and should convert __old from the argument's original type to NEW_TY. UNWRAP should contain an expression placeholder __new, and should perform the opposite conversion.

retype_return

Usage: retype_return NEW_TY WRAP UNWRAP

Marks: target

For each function marked target, change the return type of the function to NEW_TY, and use WRAP and UNWRAP to convert values to and from the original type of the argument at call sites and within the function body.

WRAP should contain an expression placeholder __old, and should convert __old from the function's original return type to NEW_TY. UNWRAP should contain an expression placeholder __new, and should perform the opposite conversion.

retype_static

Usage: retype_static NEW_TY REV_CONV_ASSIGN CONV_RVAL CONV_LVAL [CONV_LVAL_MUT]

Marks: target

For each static marked target, change the type of the static to NEW_TY, using the remaining arguments (which are all all expression templates) to convert between the old and new types at the definition and use sites.

The expression arguments are used as follows:

  • REV_CONV_ASSIGN: In direct assignments to the static and in its initializer expression, the original assigned value is wrapped (as __old) in REV_CONV_ASSIGN to produce a value of type NEW_TY.
  • CONV_RVAL: In rvalue contexts, the static is wrapped (as __new) in CONV_RVAL to produce a value of the static's old type.
  • CONV_LVAL and CONV_LVAL_MUT are similar to CONV_RVAL, but for immutable and mutable lvalue contexts respectively. Especially for CONV_LVAL_MUT, the result of wrapping should be an lvalue expression (such as a dereference or field access), not a temporary, as otherwise updates to the static could be lost. CONV_LVAL_MUT is not required for immutable statics, which cannot appear in mutable lvalue contexts.

rewrite_expr

Usage: rewrite_expr PAT REPL [FILTER]

Marks: reads FILTER, if set; may read other marks depending on PAT

For every expression in the crate matching PAT, replace it with REPL. PAT and REPL are both Rust expressions. PAT can use placeholders to capture nodes from the matched AST, and REPL can refer to those same placeholders to substitute in the captured nodes. See the matcher module for details on AST pattern matching.

If FILTER is provided, only expressions marked FILTER will be rewritten. This usage is obsolete - change PAT to marked!(PAT, FILTER) to get the same behavior.

Example:

 fn double(x: i32) -> i32 {
     x * 2
 }

After running rewrite_expr '$e * 2' '$e + $e':

 fn double(x: i32) -> i32 {
     x + x
 }

Here $e * 2 matches x * 2, capturing x as $e. Then x is substituted for $e in $e + $e, producing the final expression x + x.

rewrite_stmts

rewrite_ty

Usage: rewrite_ty PAT REPL [FILTER]

Marks: reads FILTER, if set; may read other marks depending on PAT

For every type in the crate matching PAT, replace it with REPL. PAT and REPL are both Rust types. PAT can use placeholders to capture nodes from the matched AST, and REPL can refer to those same placeholders to substitute in the captured nodes. See the matcher module for details on AST pattern matching.

If FILTER is provided, only expressions marked FILTER will be rewritten. This usage is obsolete - change PAT to marked!(PAT, FILTER) to get the same behavior.

See the documentation for rewrite_expr for an example of this style of rewriting.

select

Usage: select MARK SCRIPT

Marks: sets MARK; may set/clear other marks depending on SCRIPT

Run node-selection script SCRIPT, and apply MARK to the nodes it selects. See select::SelectOp, select::Filter, and select::parser for details on select script syntax.

select_phase2

Usage: select_phase2 MARK SCRIPT

Marks: sets MARK; may set/clear other marks depending on SCRIPT

Works like select, but stops the compiler's analyses before typechecking happens. This means type information will not available, and script commands that refer to it will fail.

set_mutability

Usage: set_mutability MUT

Marks: target

Set the mutability of all items marked target to MUT. MUT is either imm or mut. This command only affects static items (including extern statics).

set_visibility

Usage: set_visibility VIS

Marks: target

Set the visibility of all items marked target to VIS. VIS is a Rust visibility qualifier such as pub, pub(crate), or the empty string.

Doesn't handle struct field visibility, for now.

sink_lets

Usage: sink_lets

For each local variable with a trivial initializer, move the local's declaration to the innermost block containing all its uses.

"Trivial" is currently defined as no initializer (let x;) or an initializer without any side effects. This transform requires trivial assignments to avoid reordering side effects.

sink_unsafe

Usage: sink_unsafe

Marks: target

For functions marked target, convert unsafe fn f() { ... } into fn () { unsafe { ... } }. Useful once unsafe argument handling has been eliminated from the function.

static_collect_to_struct

Usage: static_collect_to_struct STRUCT VAR

Marks: target

Collect marked statics into a single static struct.

Specifically:

  1. Find all statics marked target. For each one, record its name, type, and initializer expression, then delete it.
  2. Generate a new struct definition named STRUCT. For each marked static, include a field of STRUCT with the same name and type as the static.
  3. Generate a new static mut named VAR whose type is STRUCT. Initialize it using the initializer expressions for the marked statics.
  4. For each marked static foo, replace uses of foo with VAR.foo.

Example:

 static mut FOO: i32 = 100;
 static mut BAR: bool = true;

 unsafe fn f() -> i32 {
     FOO
 }

After running static_collect_to_struct Globals G, with both statics marked:

 struct Globals {
     FOO: i32,
     BAR: bool,
 }

 static mut G: Globals = Globals {
     FOO: 100,
     BAR: true,
 };

 unsafe fn f() -> i32 {
     G.FOO
 }

static_to_local

Usage: static_to_local

Marks: target

Delete each static marked target. For each function that uses a marked static, insert a new local variable definition replicating the marked static.

Example:

 static mut FOO: i32 = 100;  // FOO: target

 unsafe fn f() -> i32 {
     FOO
 }

 unsafe fn g() -> i32 {
     FOO + 1
 }

After running static_to_local:

 // `FOO` deleted

 // `f` gains a new local, replicating `FOO`.
 unsafe fn f() -> i32 {
     let FOO: i32 = 100;
     FOO
 }

 // If multiple functions use `FOO`, each one gets its own copy.
 unsafe fn g() -> i32 {
     let FOO: i32 = 100;
     FOO + 1
 }

static_to_local_ref

Usage: static_to_local_ref

Marks: target, user

For each function marked user, replace uses of statics marked target with uses of newly-introduced reference arguments. Afterward, no user function directly accesses any target static. At call sites of user functions, a reference to the original static is passed in for each new argument if the caller is not itself a user function; otherwise, the caller's own reference argument is passed through. Note this sometimes results in functions gaining arguments corresponding to statics that the function itself does not use, but that its callees do.

Example:

 static mut FOO: i32 = 100;  // FOO: target

 unsafe fn f() -> i32 {  // f: user
     FOO
 }

 unsafe fn g() -> i32 {  // g: user
     f()
 }

 unsafe fn h() -> i32 {
     g()
 }

After running static_to_local_ref:

 static mut FOO: i32 = 100;

 // `f` is a `user` that references `FOO`, so it
 // gains a new argument `FOO_`.
 unsafe fn f(FOO_: &mut i32) -> i32 {
     // References to `FOO` are replaced with `*FOO_`
     *FOO_
 }

 // `g` is a `user` that references `FOO` indirectly,
 // via fellow `user` `f`.
 unsafe fn g(FOO_: &mut i32) -> i32 {
     // `g` passes through its own `FOO_` reference
     // when calling `f`.
     f(FOO_)
 }

 // `h` is not a `user`, so its signature is unchanged.
 unsafe fn h() -> i32 {
     // `h` passes in a reference to the original
     // static `FOO`.
     g(&mut FOO)
 }

struct_assign_to_update

Usage: struct_assign_to_update

Replace all struct field assignments with functional update expressions.

Example:

 let mut x: S = ...;
 x.f = 1;
 x.g = 2;

After running struct_assign_to_update:

 let mut x: S = ...;
 x = S { f: 1, ..x };
 x = S { g: 2, ..x };

struct_merge_updates

Usage: struct_merge_updates

Merge consecutive struct updates into a single update.

Example:

 let mut x: S = ...;
 x = S { f: 1, ..x };
 x = S { g: 2, ..x };

After running struct_assign_to_update:

 let mut x: S = ...;
 x = S { f: 1, g: 2, ..x };

test_analysis_ownership

Test command - not intended for general use.

Usage: test_analysis_ownership

Runs the ownership analysis and dumps the results to stderr.

test_analysis_type_eq

Test command - not intended for general use.

Usage: test_analysis_type_eq

Runs the type_eq analysis and logs the result (at level info).

test_debug_callees

Test command - not intended for general use.

Usage: test_debug_callees

Inspect the details of each Call expression. Used to debug RefactorCtxt::opt_callee_info.

test_f_plus_one

Test command - not intended for general use.

Usage: test_f_plus_one

Replace the expression f(__x) with __x + 1 everywhere it appears.

test_insert_remove_args

Test command - not intended for general use.

Usage: test_insert_remove_args INS REM

In each function marked target, insert new arguments at each index listed in INS (a comma-separated list of integers), then delete the arguments whose original indices are listed in REM.

This is used for testing sequence rewriting of fn argument lists.

test_one_plus_one

Test command - not intended for general use.

Usage: test_one_plus_one

Replace the expression 2 with 1 + 1 everywhere it appears.

test_reflect

Test command - not intended for general use.

Usage: test_reflect

Applies path and ty reflection on every expr in the program.

test_replace_stmts

Test command - not intended for general use.

Usage: test_replace_stmts OLD NEW

Replace statement(s) OLD with NEW everywhere it appears.

test_typeck_loop

Test command - not intended for general use.

Usage: test_typeck_loop

Runs a no-op typechecking loop for three iterations. Used to test the typechecking loop and AST re-analysis code.

type_fix_rules

Usage: type_fix_rules RULE...

Attempts to fix type errors in the crate using the provided rules. Each rule has the form "ectx, actual_ty, expected_ty => cast_expr".

  • ectx is one of rval, lval, lval_mut, or *, and determines in what kinds of expression contexts the rule applies.
  • actual_ty is a pattern to be matched against the (reflected) actual expression type.
  • expected_ty is a pattern to be matched against the (reflected) expected expression type.
  • cast_expr is a template for generating a cast expression.

For expressions in context ectx, whose actual type matches actual_ty and whose expected type matches expected_ty (and where actual != expected), the expr is substituted into cast_expr to replace the original expr with one of the expected type. During substitution, cast_expr has access to variables captured from both actual_ty and expected_ty, as well as __old containing the original (ill-typed) expression.

uninit_to_default

Obsolete - works around translator problems that no longer exist.

Usage: uninit_to_default

In local variable initializers, replace mem::uninitialized() with an appropriate default value of the variable's type.

wrap_api

Usage: wrap_api

Marks: target

For each function foo marked target:

  1. Reset the function's ABI to "Rust" (the default)
  2. Remove any #[no_mangle] or #[export_name] attributes
  3. Generate a new wrapper function called foo_wrapper with foo's old ABI and an #[export_name="foo"] attribute.

Calls to foo are left unchanged. The result is that callers from C use the wrapper function, while internal calls use foo directly, and the signature of foo can be changed freely without affecting external callers.

wrap_extern

Usage: wrap_extern

Marks: target, dest

For each foreign function marked target, generate a wrapper function in the module marked dest, and rewrite all uses of the function to call the wrapper instead.

Example:

 extern "C" {
     fn foo(x: i32) -> i32;
 }

 mod wrappers {
     // empty
 }

 fn main() {
     let x = unsafe { foo(123) };
 }

After transformation, with fn foo marked target and mod wrappers marked dest:

 extern "C" {
     fn foo(x: i32) -> i32;
 }

 mod wrappers {
     unsafe fn foo(x: i32) -> i32 {
         ::foo(x)
     }
 }

 fn main() {
     let x = unsafe { ::wrappers::foo(123) };
 }

Note that this also replaces the function in expressions that take its address, which may cause problem as the wrapper function has a different type that the original (it lacks the extern "C" ABI qualifier).

wrapping_arith_to_normal

Usage: wrapping_arith_to_normal

Replace all uses of wrapping arithmetic methods with ordinary arithmetic operators. For example, replace x.wrapping_add(y) with x + y.