Cannot borrow as immutable because it is also borrowed as mutable when verifing that a closure was called












0















I have a function that takes a closure to perform output-related logic (e.g. display to stdout):



fn handle(mut output: impl FnMut(String) -> ()) -> Result<(), String> {
// do something that produces output string `message`
let message = "example".to_string();
Ok(output(message))
}


I'm trying to write an integration test for this function, where I define a stub output function, which saves the output string to local mutable variable:



#[test]
fn should_work() {
let mut output_message = String::from("");
let output = |message: String| {
output_message = message;
};

let result = handle(output);

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


However I have error:



error[E0502]: cannot borrow `output_message` as immutable because it is also borrowed as mutable
--> src/lib.rs:18:24
|
11 | let output = |message: String| {
| ----------------- mutable borrow occurs here
12 | output_message = message;
| -------------- previous borrow occurs due to use of `output_message` in closure
...
18 | assert_eq!("blah", output_message);
| ^^^^^^^^^^^^^^ immutable borrow occurs here
19 | }
| - mutable borrow ends here


Is there any way I can test using this approach? I briefly searched for some mock crates but all of the crates don't seem to be updated very often and they are a bit overkill for my scenario anyway.



If not, any better alternative to test this function?










share|improve this question




















  • 2





    For what it's worth, your code works without any changes when enabling non-lexical lifetimes.

    – Sven Marnach
    Nov 14 '18 at 19:16











  • @SvenMarnach interesting, I don't know about that

    – Phuong Nguyen
    Nov 14 '18 at 23:22
















0















I have a function that takes a closure to perform output-related logic (e.g. display to stdout):



fn handle(mut output: impl FnMut(String) -> ()) -> Result<(), String> {
// do something that produces output string `message`
let message = "example".to_string();
Ok(output(message))
}


I'm trying to write an integration test for this function, where I define a stub output function, which saves the output string to local mutable variable:



#[test]
fn should_work() {
let mut output_message = String::from("");
let output = |message: String| {
output_message = message;
};

let result = handle(output);

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


However I have error:



error[E0502]: cannot borrow `output_message` as immutable because it is also borrowed as mutable
--> src/lib.rs:18:24
|
11 | let output = |message: String| {
| ----------------- mutable borrow occurs here
12 | output_message = message;
| -------------- previous borrow occurs due to use of `output_message` in closure
...
18 | assert_eq!("blah", output_message);
| ^^^^^^^^^^^^^^ immutable borrow occurs here
19 | }
| - mutable borrow ends here


Is there any way I can test using this approach? I briefly searched for some mock crates but all of the crates don't seem to be updated very often and they are a bit overkill for my scenario anyway.



If not, any better alternative to test this function?










share|improve this question




















  • 2





    For what it's worth, your code works without any changes when enabling non-lexical lifetimes.

    – Sven Marnach
    Nov 14 '18 at 19:16











  • @SvenMarnach interesting, I don't know about that

    – Phuong Nguyen
    Nov 14 '18 at 23:22














0












0








0








I have a function that takes a closure to perform output-related logic (e.g. display to stdout):



fn handle(mut output: impl FnMut(String) -> ()) -> Result<(), String> {
// do something that produces output string `message`
let message = "example".to_string();
Ok(output(message))
}


I'm trying to write an integration test for this function, where I define a stub output function, which saves the output string to local mutable variable:



#[test]
fn should_work() {
let mut output_message = String::from("");
let output = |message: String| {
output_message = message;
};

let result = handle(output);

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


However I have error:



error[E0502]: cannot borrow `output_message` as immutable because it is also borrowed as mutable
--> src/lib.rs:18:24
|
11 | let output = |message: String| {
| ----------------- mutable borrow occurs here
12 | output_message = message;
| -------------- previous borrow occurs due to use of `output_message` in closure
...
18 | assert_eq!("blah", output_message);
| ^^^^^^^^^^^^^^ immutable borrow occurs here
19 | }
| - mutable borrow ends here


Is there any way I can test using this approach? I briefly searched for some mock crates but all of the crates don't seem to be updated very often and they are a bit overkill for my scenario anyway.



If not, any better alternative to test this function?










share|improve this question
















I have a function that takes a closure to perform output-related logic (e.g. display to stdout):



fn handle(mut output: impl FnMut(String) -> ()) -> Result<(), String> {
// do something that produces output string `message`
let message = "example".to_string();
Ok(output(message))
}


I'm trying to write an integration test for this function, where I define a stub output function, which saves the output string to local mutable variable:



#[test]
fn should_work() {
let mut output_message = String::from("");
let output = |message: String| {
output_message = message;
};

let result = handle(output);

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


However I have error:



error[E0502]: cannot borrow `output_message` as immutable because it is also borrowed as mutable
--> src/lib.rs:18:24
|
11 | let output = |message: String| {
| ----------------- mutable borrow occurs here
12 | output_message = message;
| -------------- previous borrow occurs due to use of `output_message` in closure
...
18 | assert_eq!("blah", output_message);
| ^^^^^^^^^^^^^^ immutable borrow occurs here
19 | }
| - mutable borrow ends here


Is there any way I can test using this approach? I briefly searched for some mock crates but all of the crates don't seem to be updated very often and they are a bit overkill for my scenario anyway.



If not, any better alternative to test this function?







testing rust integration-testing






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 '18 at 15:43









Shepmaster

154k14306446




154k14306446










asked Nov 14 '18 at 16:10









Phuong NguyenPhuong Nguyen

2,2251717




2,2251717








  • 2





    For what it's worth, your code works without any changes when enabling non-lexical lifetimes.

    – Sven Marnach
    Nov 14 '18 at 19:16











  • @SvenMarnach interesting, I don't know about that

    – Phuong Nguyen
    Nov 14 '18 at 23:22














  • 2





    For what it's worth, your code works without any changes when enabling non-lexical lifetimes.

    – Sven Marnach
    Nov 14 '18 at 19:16











  • @SvenMarnach interesting, I don't know about that

    – Phuong Nguyen
    Nov 14 '18 at 23:22








2




2





For what it's worth, your code works without any changes when enabling non-lexical lifetimes.

– Sven Marnach
Nov 14 '18 at 19:16





For what it's worth, your code works without any changes when enabling non-lexical lifetimes.

– Sven Marnach
Nov 14 '18 at 19:16













@SvenMarnach interesting, I don't know about that

– Phuong Nguyen
Nov 14 '18 at 23:22





@SvenMarnach interesting, I don't know about that

– Phuong Nguyen
Nov 14 '18 at 23:22












2 Answers
2






active

oldest

votes


















3














You can put the anonymous function in a local scope, so that it is dropped by the time you assert:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = {
let output = |message: String| {
output_message = message;
};

handle(output)
};

assert!(result.is_ok());
assert_eq!("blah", output_message);
}





share|improve this answer
























  • thanks a lot, works like a charm

    – Phuong Nguyen
    Nov 14 '18 at 23:24



















2














Inline the closure:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = handle(|message| {
output_message = message;
});

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


This way, the closure is a temporary and doesn't borrow the value for a long time. As a bonus, you can avoid the type specification on the closure argument.



Or wait a few weeks until Rust 1.31 and turn on Rust 2018 mode, which has non-lexical lifetimes.






share|improve this answer
























  • thanks a lot. Coincidentally I also just saw your answer on sharing test utilities: stackoverflow.com/a/44545091/1273147

    – Phuong Nguyen
    Nov 16 '18 at 1:10











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53304433%2fcannot-borrow-as-immutable-because-it-is-also-borrowed-as-mutable-when-verifing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














You can put the anonymous function in a local scope, so that it is dropped by the time you assert:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = {
let output = |message: String| {
output_message = message;
};

handle(output)
};

assert!(result.is_ok());
assert_eq!("blah", output_message);
}





share|improve this answer
























  • thanks a lot, works like a charm

    – Phuong Nguyen
    Nov 14 '18 at 23:24
















3














You can put the anonymous function in a local scope, so that it is dropped by the time you assert:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = {
let output = |message: String| {
output_message = message;
};

handle(output)
};

assert!(result.is_ok());
assert_eq!("blah", output_message);
}





share|improve this answer
























  • thanks a lot, works like a charm

    – Phuong Nguyen
    Nov 14 '18 at 23:24














3












3








3







You can put the anonymous function in a local scope, so that it is dropped by the time you assert:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = {
let output = |message: String| {
output_message = message;
};

handle(output)
};

assert!(result.is_ok());
assert_eq!("blah", output_message);
}





share|improve this answer













You can put the anonymous function in a local scope, so that it is dropped by the time you assert:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = {
let output = |message: String| {
output_message = message;
};

handle(output)
};

assert!(result.is_ok());
assert_eq!("blah", output_message);
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 14 '18 at 16:17









TarmilTarmil

8,4132232




8,4132232













  • thanks a lot, works like a charm

    – Phuong Nguyen
    Nov 14 '18 at 23:24



















  • thanks a lot, works like a charm

    – Phuong Nguyen
    Nov 14 '18 at 23:24

















thanks a lot, works like a charm

– Phuong Nguyen
Nov 14 '18 at 23:24





thanks a lot, works like a charm

– Phuong Nguyen
Nov 14 '18 at 23:24













2














Inline the closure:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = handle(|message| {
output_message = message;
});

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


This way, the closure is a temporary and doesn't borrow the value for a long time. As a bonus, you can avoid the type specification on the closure argument.



Or wait a few weeks until Rust 1.31 and turn on Rust 2018 mode, which has non-lexical lifetimes.






share|improve this answer
























  • thanks a lot. Coincidentally I also just saw your answer on sharing test utilities: stackoverflow.com/a/44545091/1273147

    – Phuong Nguyen
    Nov 16 '18 at 1:10
















2














Inline the closure:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = handle(|message| {
output_message = message;
});

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


This way, the closure is a temporary and doesn't borrow the value for a long time. As a bonus, you can avoid the type specification on the closure argument.



Or wait a few weeks until Rust 1.31 and turn on Rust 2018 mode, which has non-lexical lifetimes.






share|improve this answer
























  • thanks a lot. Coincidentally I also just saw your answer on sharing test utilities: stackoverflow.com/a/44545091/1273147

    – Phuong Nguyen
    Nov 16 '18 at 1:10














2












2








2







Inline the closure:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = handle(|message| {
output_message = message;
});

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


This way, the closure is a temporary and doesn't borrow the value for a long time. As a bonus, you can avoid the type specification on the closure argument.



Or wait a few weeks until Rust 1.31 and turn on Rust 2018 mode, which has non-lexical lifetimes.






share|improve this answer













Inline the closure:



#[test]
fn should_work() {
let mut output_message = String::from("");

let result = handle(|message| {
output_message = message;
});

assert!(result.is_ok());
assert_eq!("blah", output_message);
}


This way, the closure is a temporary and doesn't borrow the value for a long time. As a bonus, you can avoid the type specification on the closure argument.



Or wait a few weeks until Rust 1.31 and turn on Rust 2018 mode, which has non-lexical lifetimes.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 15 '18 at 15:42









ShepmasterShepmaster

154k14306446




154k14306446













  • thanks a lot. Coincidentally I also just saw your answer on sharing test utilities: stackoverflow.com/a/44545091/1273147

    – Phuong Nguyen
    Nov 16 '18 at 1:10



















  • thanks a lot. Coincidentally I also just saw your answer on sharing test utilities: stackoverflow.com/a/44545091/1273147

    – Phuong Nguyen
    Nov 16 '18 at 1:10

















thanks a lot. Coincidentally I also just saw your answer on sharing test utilities: stackoverflow.com/a/44545091/1273147

– Phuong Nguyen
Nov 16 '18 at 1:10





thanks a lot. Coincidentally I also just saw your answer on sharing test utilities: stackoverflow.com/a/44545091/1273147

– Phuong Nguyen
Nov 16 '18 at 1:10


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53304433%2fcannot-borrow-as-immutable-because-it-is-also-borrowed-as-mutable-when-verifing%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine