Skip to content

Commit a7d91c3

Browse files
committed
Apply HIR local events in clean state
1 parent f5a1f50 commit a7d91c3

2 files changed

Lines changed: 84 additions & 30 deletions

File tree

src/checks/body.rs

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use crate::analyzer::Analyzer;
22
use crate::diagnostic::{Diagnostic, code};
33
use crate::hir::{
4-
CallResolution, HirBindingKind, HirEffectEventKind, HirReturnProof, HirTypeKind,
5-
ResolvedCalleeKind,
4+
CallResolution, HirEffectEventKind, HirReturnProof, HirTypeKind, ResolvedCalleeKind,
65
};
76
use crate::syntax::ast::{Block, Callee, DataEffect, Expr, FunctionDecl, Item, LetKind, Stmt};
87

@@ -30,14 +29,7 @@ fn seed_function_bindings(analyzer: &Analyzer<'_>, function: &FunctionDecl, stat
3029
let Some(body) = analyzer.hir.function_body(&function.name) else {
3130
return;
3231
};
33-
for binding in &body.bindings {
34-
if binding.kind != HirBindingKind::Param {
35-
continue;
36-
}
37-
if let Some(type_name) = &binding.type_name {
38-
state.record_type(binding.name.clone(), type_name.clone());
39-
}
40-
}
32+
state.seed_params(&body.bindings);
4133
}
4234

4335
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -242,33 +234,15 @@ fn apply_move_events(
242234
span: &crate::diagnostic::Span,
243235
state: &mut BodyState,
244236
) {
245-
for event in analyzer.hir.effect_events(span) {
246-
if !matches!(
247-
event.kind,
248-
HirEffectEventKind::Manage | HirEffectEventKind::Take
249-
) {
250-
continue;
251-
}
252-
if state.locals.contains(&event.binding_name) {
253-
state.mark_moved(&event.binding_name, event.span.clone());
254-
}
255-
}
237+
state.apply_move_events(analyzer.hir.effect_events(span));
256238
}
257239

258240
fn apply_retention_events(
259241
analyzer: &Analyzer<'_>,
260242
span: &crate::diagnostic::Span,
261243
state: &mut BodyState,
262244
) {
263-
for event in analyzer.hir.effect_events(span) {
264-
if !matches!(event.kind, HirEffectEventKind::Retain { .. }) {
265-
continue;
266-
}
267-
if !state.locals.contains(&event.binding_name) {
268-
continue;
269-
}
270-
state.mark_retained(&event.binding_name);
271-
}
245+
state.apply_retention_events(analyzer.hir.effect_events(span));
272246
}
273247

274248
fn check_moved_uses_in_stmt(analyzer: &mut Analyzer<'_>, statement: &Stmt, state: &BodyState) {

src/checks/local.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::collections::{HashMap, HashSet};
22

33
use crate::diagnostic::Span;
4+
use crate::hir::{HirBinding, HirBindingKind, HirEffectEvent, HirEffectEventKind};
45

56
use super::body::Flow;
67

@@ -14,6 +15,17 @@ pub(crate) struct BodyState {
1415
}
1516

1617
impl BodyState {
18+
pub(crate) fn seed_params(&mut self, bindings: &[HirBinding]) {
19+
for binding in bindings {
20+
if binding.kind != HirBindingKind::Param {
21+
continue;
22+
}
23+
if let Some(type_name) = &binding.type_name {
24+
self.record_type(binding.name.clone(), type_name.clone());
25+
}
26+
}
27+
}
28+
1729
pub(crate) fn bind_managed(&mut self, name: impl Into<String>) {
1830
self.managed.insert(name.into());
1931
}
@@ -36,6 +48,31 @@ impl BodyState {
3648
pub(crate) fn mark_retained(&mut self, name: &str) {
3749
self.clean_locals.remove(name);
3850
}
51+
52+
pub(crate) fn apply_move_events(&mut self, events: &[HirEffectEvent]) {
53+
for event in events {
54+
if !matches!(
55+
event.kind,
56+
HirEffectEventKind::Manage | HirEffectEventKind::Take
57+
) {
58+
continue;
59+
}
60+
if self.locals.contains(&event.binding_name) {
61+
self.mark_moved(&event.binding_name, event.span.clone());
62+
}
63+
}
64+
}
65+
66+
pub(crate) fn apply_retention_events(&mut self, events: &[HirEffectEvent]) {
67+
for event in events {
68+
if !matches!(event.kind, HirEffectEventKind::Retain { .. }) {
69+
continue;
70+
}
71+
if self.locals.contains(&event.binding_name) {
72+
self.mark_retained(&event.binding_name);
73+
}
74+
}
75+
}
3976
}
4077

4178
pub(crate) fn merge_if_state(
@@ -158,3 +195,46 @@ fn merge_fallthrough_states(base: &BodyState, left: &BodyState, right: &BodyStat
158195
.collect(),
159196
}
160197
}
198+
199+
#[cfg(test)]
200+
mod tests {
201+
use super::*;
202+
203+
fn span(line: usize) -> Span {
204+
Span {
205+
file: "test.rss".to_string(),
206+
line,
207+
column: 1,
208+
length: 1,
209+
}
210+
}
211+
212+
#[test]
213+
fn applies_move_and_retain_events_to_clean_local_state() {
214+
let mut state = BodyState::default();
215+
state.bind_local("image");
216+
state.bind_local("cached");
217+
218+
state.apply_retention_events(&[HirEffectEvent {
219+
function_name: "run".to_string(),
220+
kind: HirEffectEventKind::Retain {
221+
callee: "Cache.store".to_string(),
222+
param: "value".to_string(),
223+
},
224+
binding_name: "cached".to_string(),
225+
span: span(10),
226+
value_span: span(10),
227+
}]);
228+
state.apply_move_events(&[HirEffectEvent {
229+
function_name: "run".to_string(),
230+
kind: HirEffectEventKind::Manage,
231+
binding_name: "image".to_string(),
232+
span: span(11),
233+
value_span: span(11),
234+
}]);
235+
236+
assert!(!state.clean_locals.contains("cached"));
237+
assert!(!state.clean_locals.contains("image"));
238+
assert_eq!(state.moved["image"].line, 11);
239+
}
240+
}

0 commit comments

Comments
 (0)