diff options
author | Paul Daniel Faria <[email protected]> | 2020-06-27 16:55:54 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-06-27 16:55:54 +0100 |
commit | b7e25ba854a5ca0f1dee7082c113170876358632 (patch) | |
tree | 36ffee1ed6acbc5b6669b78d8332b7119bb3ff5c /crates/ra_hir_ty/src | |
parent | b1992b469cae689f7de01ea9031962735a409198 (diff) |
Improve perf of finding unsafe exprs
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/unsafe_validation.rs | 88 |
1 files changed, 39 insertions, 49 deletions
diff --git a/crates/ra_hir_ty/src/unsafe_validation.rs b/crates/ra_hir_ty/src/unsafe_validation.rs index e2353404b..aad13d99c 100644 --- a/crates/ra_hir_ty/src/unsafe_validation.rs +++ b/crates/ra_hir_ty/src/unsafe_validation.rs | |||
@@ -60,12 +60,6 @@ pub struct UnsafeExpr { | |||
60 | pub inside_unsafe_block: bool, | 60 | pub inside_unsafe_block: bool, |
61 | } | 61 | } |
62 | 62 | ||
63 | impl UnsafeExpr { | ||
64 | fn new(expr: ExprId) -> Self { | ||
65 | Self { expr, inside_unsafe_block: false } | ||
66 | } | ||
67 | } | ||
68 | |||
69 | pub fn unsafe_expressions( | 63 | pub fn unsafe_expressions( |
70 | db: &dyn HirDatabase, | 64 | db: &dyn HirDatabase, |
71 | infer: &InferenceResult, | 65 | infer: &InferenceResult, |
@@ -73,59 +67,55 @@ pub fn unsafe_expressions( | |||
73 | ) -> Vec<UnsafeExpr> { | 67 | ) -> Vec<UnsafeExpr> { |
74 | let mut unsafe_exprs = vec![]; | 68 | let mut unsafe_exprs = vec![]; |
75 | let body = db.body(def); | 69 | let body = db.body(def); |
76 | for (id, expr) in body.exprs.iter() { | 70 | walk_unsafe(&mut unsafe_exprs, db, infer, &body, body.body_expr, false); |
77 | match expr { | 71 | |
78 | Expr::Call { callee, .. } => { | 72 | unsafe_exprs |
79 | let ty = &infer[*callee]; | 73 | } |
80 | if let &Ty::Apply(ApplicationTy { | 74 | |
81 | ctor: TypeCtor::FnDef(CallableDef::FunctionId(func)), | 75 | fn walk_unsafe( |
82 | .. | 76 | unsafe_exprs: &mut Vec<UnsafeExpr>, |
83 | }) = ty | 77 | db: &dyn HirDatabase, |
84 | { | 78 | infer: &InferenceResult, |
85 | if db.function_data(func).is_unsafe { | 79 | body: &Body, |
86 | unsafe_exprs.push(UnsafeExpr::new(id)); | 80 | current: ExprId, |
87 | } | 81 | inside_unsafe_block: bool, |
82 | ) { | ||
83 | let expr = &body.exprs[current]; | ||
84 | match expr { | ||
85 | Expr::Call { callee, .. } => { | ||
86 | let ty = &infer[*callee]; | ||
87 | if let &Ty::Apply(ApplicationTy { | ||
88 | ctor: TypeCtor::FnDef(CallableDef::FunctionId(func)), | ||
89 | .. | ||
90 | }) = ty | ||
91 | { | ||
92 | if db.function_data(func).is_unsafe { | ||
93 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | ||
88 | } | 94 | } |
89 | } | 95 | } |
90 | Expr::MethodCall { .. } => { | 96 | } |
91 | if infer | 97 | Expr::MethodCall { .. } => { |
92 | .method_resolution(id) | 98 | if infer |
93 | .map(|func| db.function_data(func).is_unsafe) | 99 | .method_resolution(current) |
94 | .unwrap_or(false) | 100 | .map(|func| db.function_data(func).is_unsafe) |
95 | { | 101 | .unwrap_or(false) |
96 | unsafe_exprs.push(UnsafeExpr::new(id)); | 102 | { |
97 | } | 103 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
98 | } | 104 | } |
99 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { | 105 | } |
100 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { | 106 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { |
101 | unsafe_exprs.push(UnsafeExpr::new(id)); | 107 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { |
102 | } | 108 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
103 | } | 109 | } |
104 | _ => {} | ||
105 | } | 110 | } |
111 | _ => {} | ||
106 | } | 112 | } |
107 | 113 | ||
108 | for unsafe_expr in &mut unsafe_exprs { | ||
109 | unsafe_expr.inside_unsafe_block = | ||
110 | is_in_unsafe(&body, body.body_expr, unsafe_expr.expr, false); | ||
111 | } | ||
112 | |||
113 | unsafe_exprs | ||
114 | } | ||
115 | |||
116 | fn is_in_unsafe(body: &Body, current: ExprId, needle: ExprId, within_unsafe: bool) -> bool { | ||
117 | if current == needle { | ||
118 | return within_unsafe; | ||
119 | } | ||
120 | |||
121 | let expr = &body.exprs[current]; | ||
122 | if let &Expr::Unsafe { body: child } = expr { | 114 | if let &Expr::Unsafe { body: child } = expr { |
123 | return is_in_unsafe(body, child, needle, true); | 115 | return walk_unsafe(unsafe_exprs, db, infer, body, child, true); |
124 | } | 116 | } |
125 | 117 | ||
126 | let mut found = false; | ||
127 | expr.walk_child_exprs(|child| { | 118 | expr.walk_child_exprs(|child| { |
128 | found = found || is_in_unsafe(body, child, needle, within_unsafe); | 119 | walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block); |
129 | }); | 120 | }); |
130 | found | ||
131 | } | 121 | } |