1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use rustc::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability};
use syntax::ast::{Crate, Expr, ExprKind, Mutability, UnOp};
use syntax::ptr::P;
use c2rust_ast_builder::mk;
use crate::ast_manip::MutVisitNodes;
use crate::command::{CommandState, Registry};
use crate::driver::Phase;
use crate::transform::Transform;
use crate::RefactorCtxt;
struct CanonicalizeRefs;
impl Transform for CanonicalizeRefs {
fn transform(&self, krate: &mut Crate, _st: &CommandState, cx: &RefactorCtxt) {
MutVisitNodes::visit(krate, |expr: &mut P<Expr>| {
let hir_expr = cx.hir_map().expect_expr(expr.id);
let parent = cx.hir_map().get_parent_did(expr.id);
let tables = cx.ty_ctxt().typeck_tables_of(parent);
for adjustment in tables.expr_adjustments(hir_expr) {
match adjustment.kind {
Adjust::Deref(_) => {
*expr = mk().unary_expr(UnOp::Deref, expr.clone());
}
Adjust::Borrow(AutoBorrow::Ref(_, ref mutability)) => {
let mutability = match mutability {
AutoBorrowMutability::Mutable{..} => Mutability::Mutable,
AutoBorrowMutability::Immutable => Mutability::Immutable,
};
*expr = mk().set_mutbl(mutability).addr_of_expr(expr.clone());
}
_ => {},
}
}
});
}
fn min_phase(&self) -> Phase {
Phase::Phase3
}
}
struct RemoveUnnecessaryRefs;
impl Transform for RemoveUnnecessaryRefs {
fn transform(&self, krate: &mut Crate, _st: &CommandState, _cx: &RefactorCtxt) {
MutVisitNodes::visit(krate, |expr: &mut P<Expr>| {
match &mut expr.node {
ExprKind::MethodCall(_path, args) => {
let (receiver, rest) = args.split_first_mut().unwrap();
remove_reborrow(receiver);
remove_ref(receiver);
remove_all_derefs(receiver);
for arg in rest {
remove_reborrow(arg);
}
}
ExprKind::Call(_callee, args) => {
for arg in args.iter_mut() {
remove_reborrow(arg);
}
}
_ => {}
}
});
}
fn min_phase(&self) -> Phase {
Phase::Phase3
}
}
fn remove_ref(expr: &mut P<Expr>) {
match &expr.node {
ExprKind::AddrOf(_, inner) => *expr = inner.clone(),
_ => {}
}
}
fn remove_all_derefs(expr: &mut P<Expr>) {
match &expr.node {
ExprKind::Unary(UnOp::Deref, inner) => {
*expr = inner.clone();
remove_all_derefs(expr);
}
_ => {}
}
}
fn remove_reborrow(expr: &mut P<Expr>) {
if let ExprKind::AddrOf(_, ref subexpr) = expr.node {
if let ExprKind::Unary(UnOp::Deref, ref subexpr) = subexpr.node {
*expr = subexpr.clone();
remove_reborrow(expr);
}
}
}
pub fn register_commands(reg: &mut Registry) {
use super::mk;
reg.register("canonicalize_refs", |_args| mk(CanonicalizeRefs));
reg.register("remove_unnecessary_refs", |_args| mk(RemoveUnnecessaryRefs));
}