11use std:: collections:: { HashMap , HashSet } ;
22
33use crate :: diagnostic:: Span ;
4+ use crate :: hir:: { HirBinding , HirBindingKind , HirEffectEvent , HirEffectEventKind } ;
45
56use super :: body:: Flow ;
67
@@ -14,6 +15,17 @@ pub(crate) struct BodyState {
1415}
1516
1617impl 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
4178pub ( 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