Home > Blockchain >  How can a local variable be assigned in previous iteration of loop
How can a local variable be assigned in previous iteration of loop

Time:12-03

Just a question so I can better understand Rust.

Why does this fail:

for event in rulesengine::RuleEvent::into_enum_iter()
{
  let mut event_stats: payloads::EventStats;
  event_stats.name = rulesengine::RuleEvent::to_string(&event);
  event_stats.event_count = event_counters.event_count[event as usize];
  event_stats.event_participant_count = event_counters.event_participant_count[event as usize];
  event_stats.event_trigger_count = event_counters.event_trigger_count[event as usize];
  rules_stats.event_stats.push(event_stats);
}

With:

error[E0382]: assign to part of moved value: `event_stats`
   --> src/motion.rs:317:37
    |
316 | ...                       let mut event_stats: payloads::EventStats;
    |                               --------------- move occurs because `event_stats` has type `payloads::EventStats`, which does not implement the `Copy` trait
317 | ...                       event_stats.name = rulesengine::RuleEvent::to_string(&event).clone();
    |                           ^^^^^^^^^^^^^^^^ value partially assigned here after move
...
323 | ...                   },
    |                       - value moved here, in previous iteration of loop

error: aborting due to previous error

When this works:

for event in rulesengine::RuleEvent::into_enum_iter()
{
  let name = rulesengine::RuleEvent::to_string(&event);
  let event_count = event_counters.event_count[event as usize];
  let event_participant_count = event_counters.event_participant_count[event as usize];
  let event_trigger_count = event_counters.event_trigger_count[event as usize];
  let event_stats = payloads::EventStats { name, event_count, event_participant_count, event_trigger_count };
  rules_stats.event_stats.push(event_stats);
}

or even better

for event in rulesengine::RuleEvent::into_enum_iter()
{
  let event_stats = payloads::EventStats
  {
    name: rulesengine::RuleEvent::to_string(&event),
    event_count: event_counters.event_count[event as usize],
    event_participant_count: event_counters.event_participant_count[event as usize],
    event_trigger_count: event_counters.event_trigger_count[event as usize],
  };
  rules_stats.event_stats.push(event_stats);
}

The variable event_stats is mutable yes, but local. It doesn't exist in the "previous iteration of loop" to be moved.

CodePudding user response:

I believe the error is a mis-diagnosis of the problem. There have been compiler bugs in the past where the message incorrectly blames the loop for uninitialized variables. Perhaps this is another one of those cases.


The core issue is you are trying to assign a field to an uninitialized value:

let mut event_stats: payloads::EventStats;
event_stats.name = ...;

You have declared event_stats but have not initialized it. Rust does not allow you to piece-wise initialize a struct, at least not without a lot of extra juggling.

Both your working solutions create event_stats from a struct literal:

let event_stats = payloads::EventStats { name: ..., ... };

which is the correct way to initialize a struct.

  • Related