私は借りたチェッカーであるRustの最終的なボスと戦っています。これは私が取り組んでいるmio
反応ネットワークアプリケーションの簡略化されたバージョンです。私はあまりにも多くの時間を費やして、手元にあるタスクの正しいデータ構造を見つけ出しました。新しい接続を受け入れることができるリスニングソケットを反復しながら接続を登録したいと思います。エイリアシングフリーのデータ構造を見つける方法
次のコードを参照するか、Rust playgroundで確認してください。 HashMap::get_mut
は、self
の1フィールドに1の値に一意のボローを返します。したがって、self
をThing::act
に渡すことはできません。なぜそれが起こるのか、実行時にどのように問題が生じるのか理解していますが、そのような問題を避けるためにデータ構造をどのようにリファクタリングするのか分かりません。
use std::collections::HashMap;
trait ThingSet {
fn register(&mut self, thing: Box<Thing>);
}
trait Thing {
fn act(&mut self, reg: &mut ThingSet);
}
struct Stream;
impl Thing for Stream {
fn act(&mut self, reg: &mut ThingSet) {}
}
struct Listener;
impl Thing for Listener {
fn act(&mut self, reg: &mut ThingSet) {
if true {
let mut stream = Stream {};
reg.register(Box::new(stream));
}
}
}
struct Loop {
next: usize,
things: HashMap<usize, Box<Thing>>,
}
impl Loop {
fn new() -> Loop {
Loop { next: 1, things: HashMap::new(), }
}
fn run(&mut self) {
let mut needs_action = Vec::<&mut Box<Thing>>::new();
{
// modeling a connection on one of the listeners...
if let Some(t) = self.things.get_mut(&1usize) {
needs_action.push(t);
}
}
for t in needs_action {
t.act(self as &mut ThingSet);
}
}
}
impl ThingSet for Loop {
fn register(&mut self, thing: Box<Thing>) {
self.things.insert(self.next, thing);
self.next += 1;
}
}
fn main() {
let mut l = Loop::new();
let mut p1 = Listener {};
let mut p2 = Listener {};
l.register(Box::new(p1));
l.register(Box::new(p2));
l.run();
}
私は借用チェッカーが何をし、何が許可されていないのかを説明した良いチュートリアルを見つけることができました。私は、許可されていない参照を避けることができる代替データ構造を見つける方法に関する良いチュートリアルを見つけることができませんでした。
この特定の問題を改造する方法を教えてください。
をplay.rust-lang.org/?gist=710aefc653b320c653f289f5e3eee972とhttps://play.rust-lang.org/?gist=4fecb8d2b584252fd6b6e687db34de5a – wigy
週末の前に@ breedenの回答を受け入れる人がいます。誰かが静的このユースケースのチェックを借りてください。 – wigy
安全な解決策では、 'needs_action'のエントリを別のリスナーの' act'から削除すると、use-after-freeという結果になるので、削除しました。また、彼女の – LinearZoetrope