Refactoring Commands
abstract
autoretype
bitcast_retype
bytestr_to_str
canonicalize_externs
canonicalize_structs
char_literals
clear_marks
commit
convert_cast_as_ptr
convert_format_args
convert_printfs
copy_marks
create_item
delete_items
delete_marks
fix_unused_unsafe
fold_let_assign
func_to_method
generalize_items
ionize
let_x_uninitialized
link_funcs
link_incomplete_types
mark_arg_uses
mark_callers
mark_field_uses
mark_pub_in_mod
mark_related_types
mark_uses
ownership_annotate
ownership_mark_pointers
ownership_split_variants
pick_node
print_marks
print_spans
reconstruct_for_range
reconstruct_while
remove_null_terminator
remove_redundant_casts
remove_redundant_let_types
remove_unused_labels
rename_items_regex
rename_marks
rename_struct
rename_unnamed
reoganize_definitions
replace_items
retype_argument
retype_return
retype_static
rewrite_expr
rewrite_stmts
rewrite_ty
select
select_phase2
set_mutability
set_visibility
sink_lets
sink_unsafe
static_collect_to_struct
static_to_local
static_to_local_ref
struct_assign_to_update
struct_merge_updates
test_analysis_ownership
test_analysis_type_eq
test_debug_callees
test_f_plus_one
test_insert_remove_args
test_one_plus_one
test_reflect
test_replace_stmts
test_typeck_loop
type_fix_rules
uninit_to_default
wrap_api
wrap_extern
wrapping_arith_to_normal
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 #include
s 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 mod
s 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 mod
s 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 let
s 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 Ident
s 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-transpile
d 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
) inREV_CONV_ASSIGN
to produce a value of typeNEW_TY
.CONV_RVAL
: In rvalue contexts, the static is wrapped (as__new
) inCONV_RVAL
to produce a value of the static's old type.CONV_LVAL
andCONV_LVAL_MUT
are similar toCONV_RVAL
, but for immutable and mutable lvalue contexts respectively. Especially forCONV_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:
- Find all statics marked
target
. For each one, record its name, type, and initializer expression, then delete it. - Generate a new struct definition named
STRUCT
. For each marked static, include a field ofSTRUCT
with the same name and type as the static. - Generate a new
static mut
namedVAR
whose type isSTRUCT
. Initialize it using the initializer expressions for the marked statics. - For each marked static
foo
, replace uses offoo
withVAR.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 ofrval
,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
:
- Reset the function's ABI to
"Rust"
(the default) - Remove any
#[no_mangle]
or#[export_name]
attributes - Generate a new wrapper function called
foo_wrapper
withfoo
'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
.