@@ -12,70 +12,21 @@ pub struct CloneUsage {
1212 /// Whether the clone value is mutated.
1313 pub clone_consumed_or_mutated : bool ,
1414}
15+
1516pub fn visit_clone_usage (
1617 cloned : mir:: Local ,
1718 clone : mir:: Local ,
1819 mir : & mir:: Body < ' _ > ,
1920 bb : mir:: BasicBlock ,
2021) -> CloneUsage {
21- struct V {
22- cloned : mir:: Local ,
23- clone : mir:: Local ,
24- result : CloneUsage ,
25- }
26- impl < ' tcx > mir:: visit:: Visitor < ' tcx > for V {
27- fn visit_basic_block_data ( & mut self , block : mir:: BasicBlock , data : & mir:: BasicBlockData < ' tcx > ) {
28- let statements = & data. statements ;
29- for ( statement_index, statement) in statements. iter ( ) . enumerate ( ) {
30- self . visit_statement ( statement, mir:: Location { block, statement_index } ) ;
31- }
32-
33- self . visit_terminator (
34- data. terminator ( ) ,
35- mir:: Location {
36- block,
37- statement_index : statements. len ( ) ,
38- } ,
39- ) ;
40- }
41-
42- fn visit_place ( & mut self , place : & mir:: Place < ' tcx > , ctx : PlaceContext , loc : mir:: Location ) {
43- let local = place. local ;
44-
45- if local == self . cloned
46- && !matches ! (
47- ctx,
48- PlaceContext :: MutatingUse ( MutatingUseContext :: Drop ) | PlaceContext :: NonUse ( _)
49- )
50- {
51- self . result . cloned_used = true ;
52- self . result . cloned_consume_or_mutate_loc = self . result . cloned_consume_or_mutate_loc . or_else ( || {
53- matches ! (
54- ctx,
55- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move )
56- | PlaceContext :: MutatingUse ( MutatingUseContext :: Borrow )
57- )
58- . then ( || loc)
59- } ) ;
60- } else if local == self . clone {
61- match ctx {
62- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move )
63- | PlaceContext :: MutatingUse ( MutatingUseContext :: Borrow ) => {
64- self . result . clone_consumed_or_mutated = true ;
65- } ,
66- _ => { } ,
67- }
68- }
69- }
70- }
71-
7222 let init = CloneUsage {
7323 cloned_used : false ,
7424 cloned_consume_or_mutate_loc : None ,
7525 // Consider non-temporary clones consumed.
7626 // TODO: Actually check for mutation of non-temporaries.
7727 clone_consumed_or_mutated : mir. local_kind ( clone) != mir:: LocalKind :: Temp ,
7828 } ;
29+
7930 traversal:: ReversePostorder :: new ( mir, bb)
8031 . skip ( 1 )
8132 . fold ( init, |usage, ( tbb, tdata) | {
@@ -100,3 +51,55 @@ pub fn visit_clone_usage(
10051 v. result
10152 } )
10253}
54+
55+ struct V {
56+ cloned : mir:: Local ,
57+ clone : mir:: Local ,
58+ result : CloneUsage ,
59+ }
60+
61+ impl < ' tcx > mir:: visit:: Visitor < ' tcx > for V {
62+ fn visit_basic_block_data ( & mut self , block : mir:: BasicBlock , data : & mir:: BasicBlockData < ' tcx > ) {
63+ let statements = & data. statements ;
64+ for ( statement_index, statement) in statements. iter ( ) . enumerate ( ) {
65+ self . visit_statement ( statement, mir:: Location { block, statement_index } ) ;
66+ }
67+
68+ self . visit_terminator (
69+ data. terminator ( ) ,
70+ mir:: Location {
71+ block,
72+ statement_index : statements. len ( ) ,
73+ } ,
74+ ) ;
75+ }
76+
77+ fn visit_place ( & mut self , place : & mir:: Place < ' tcx > , ctx : PlaceContext , loc : mir:: Location ) {
78+ let local = place. local ;
79+
80+ if local == self . cloned
81+ && !matches ! (
82+ ctx,
83+ PlaceContext :: MutatingUse ( MutatingUseContext :: Drop ) | PlaceContext :: NonUse ( _)
84+ )
85+ {
86+ self . result . cloned_used = true ;
87+ self . result . cloned_consume_or_mutate_loc = self . result . cloned_consume_or_mutate_loc . or_else ( || {
88+ matches ! (
89+ ctx,
90+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move )
91+ | PlaceContext :: MutatingUse ( MutatingUseContext :: Borrow )
92+ )
93+ . then ( || loc)
94+ } ) ;
95+ } else if local == self . clone {
96+ match ctx {
97+ PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move )
98+ | PlaceContext :: MutatingUse ( MutatingUseContext :: Borrow ) => {
99+ self . result . clone_consumed_or_mutated = true ;
100+ } ,
101+ _ => { } ,
102+ }
103+ }
104+ }
105+ }
0 commit comments