Borrow check in function call and its arguments

I was trying to implement something like a visitor pattern. I wrapped the output into a struct:

struct DumpGraphviz {
    out: Box<dyn Write>,
    id: u32 
}

so I can create a object visit with type DumpGraphviz and pass it into function.
When I try to create a lot of output using map, I have to write:

// fn dump_node(&self, visit: &mut DumpGraphviz) -> u32;
// let v = vector of some data
let children : Vec<_> = v.iter().map(|n| n.dump_node(visit)).collect();
visit.dump_children("VARIABLE_DECL_LIST_NODE", &children)

My question is that, why I cannot put these into one line, like:

// let v = vector of some data
visit.dump_children("VARIABLE_DECL_LIST_NODE",
    &v.iter().map(|n| n.dump_node(visit)).collect::<Vec<_>>())

Compiler will complain that visit is first borrow when calling dump_children, and second borrow occurred at dump_node(visit)
This seems a little weird, since preparing the argument of dump_children should not conflict with the real call.,Can somebody explain why compiler think the code has problem?

Yes, the code is valid and it is hoped that borrow checker would accept such code in the future. More on this here: Baby Steps

It is just that this is rather tricky to implement. It is the next target now NLL is done.

Given expression foo.bar(baz()) it's easy to assume it's executed as:

let tmp = baz();
foo.bar(tmp);

but it's actually:

let tmp1 = &foo;
let tmp2 = baz(); // baz runs while foo is borrowed
tmp1.bar(tmp2);

This becomes more obvious when you change the expression slightly to make evaluation visibe:

foo().bar(baz());

Now you can see that foo() should execute before baz(). In Rust order of borrows follows the order of execution, so the left side of . is borrowed first.

Thank for you answers. Now I understand the consider behind compiler implementation.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.