Rust temporary variable lifetime in method chaining The 2019 Stack Overflow Developer Survey Results Are InIs there a way to use match() in rust when modifying the selector?Using a static integer in the definition of a structFactory method: instance does not live long enoughWhy are explicit lifetimes needed in Rust?Encapsulating sequentially initialized state with self-references in Rust structRust lifetime for database connection bundleRust function that allocates memory and calls a C++ callback crashesHow does the dropping of temporary values work in rust?Matching against the enclosing function's return typeTemporary Lifetime in Arc in Rust
Should I write numbers in words or as numerals when there are multiple next to each other?
What is the meaning of Triage in Cybersec world?
What are the motivations for publishing new editions of an existing textbook, beyond new discoveries in a field?
Landlord wants to switch my lease to a "Land contract" to "get back at the city"
Does a dangling wire really electrocute me if I'm standing in water?
Does light intensity oscillate really fast since it is a wave?
How was Skylab's orbit inclination chosen?
I see my dog run
Patience, young "Padovan"
Is three citations per paragraph excessive for undergraduate research paper?
Geography at the pixel level
How come people say “Would of”?
Lethal sonic weapons
Falsification in Math vs Science
Is "plugging out" electronic devices an American expression?
Is there a name of the flying bionic bird?
Is it possible for the two major parties in the UK to form a coalition with each other instead of a much smaller party?
What does Linus Torvalds mean when he says that Git "never ever" tracks a file?
Which Sci-Fi work first showed weapon of galactic-scale mass destruction?
Does duplicating a spell with Wish count as casting that spell?
Why could you hear an Amstrad CPC working?
Why is the maximum length of openwrt’s root password 8 characters?
How can I create a character who can assume the widest possible range of creature sizes?
Monty Hall variation
Rust temporary variable lifetime in method chaining
The 2019 Stack Overflow Developer Survey Results Are InIs there a way to use match() in rust when modifying the selector?Using a static integer in the definition of a structFactory method: instance does not live long enoughWhy are explicit lifetimes needed in Rust?Encapsulating sequentially initialized state with self-references in Rust structRust lifetime for database connection bundleRust function that allocates memory and calls a C++ callback crashesHow does the dropping of temporary values work in rust?Matching against the enclosing function's return typeTemporary Lifetime in Arc in Rust
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I'm trying to learn Rust's lifetime rules by comparing it to similar concepts in C++, which I'm more familiar with. Most of the time, my intuition works really well and I can make sense the rule. However, in the following case, I'm not sure if my understanding is correct or not.
In Rust, a temporary value's lifetime is the end of its statement, except when the last temporary value is bound to a name using let.
struct A(u8);
struct B(u8);
impl A
fn get_b(&mut self) -> Option<B>
Some(B(self.0))
fn a(v: u8) -> A
A(v)
// temporary A's lifetime is the end of the statement
// temporary B binds to a name so lives until the enclosing block
let b = a(1).get_b();
// temporary A's lifetime is the end of the statement
// temporary B's lifetime extends to the enclosing block,
// so that taking reference of temporary works similar as above
let b = &a(2).get_b();
If the temporary value is in an if condition, according to the reference, the lifetime is instead limited to the conditional expression.
// Both temporary A and temporary B drops before printing some
if a(3).get_b().unwrap().val <= 3
println!("some");
Now to the question:
If putting let in if condition, because of pattern matching, we are binding to the inner part of the temporary value. I'd expect the temporary value bound by let to be extended to the enclosing block, while other temporary values should still have a lifetime limited by the if condition.
(In this case actually everything is copied I would say even temporary B can be dropped, but that's a separate question.)
However, both temporaries' lifetimes are extended to the enclosing if block.
// Both temporary A and temporary B's lifetime are extended to the end of the enclosing block,
// which is the if statement
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
Should this be considered an inconsistency in Rust? Or am I misunderstanding and there is a consistent rule that can explain this behavior?
Full code example:
- playground
- The same thing implemented in C++ that matches my expectation
Note the output from Rust is
some 4
Drop B 4
Drop A 4
while the output from C++ is
Drop A 4
some 4
Drop B 4
I have read this Reddit thread and Rust issue, which I think is quite relevant, but I still can't find a clear set of lifetime rule that works for all the cases in Rust.
Update:
What I'm unclear about is why the temporary lifetime rule about if conditional expression does not apply to if let. I think the let Some(B(v @ 0...4)) = a(4).get_b() should be the conditional expression, and thus the temporary A's lifetime should be limited by that, rather than the entire if statement.
The behaviour of extending temporary B's lifetime to the entire if statement is expected, because that is borrowed by the pattern matching.
rust
|
show 1 more comment
I'm trying to learn Rust's lifetime rules by comparing it to similar concepts in C++, which I'm more familiar with. Most of the time, my intuition works really well and I can make sense the rule. However, in the following case, I'm not sure if my understanding is correct or not.
In Rust, a temporary value's lifetime is the end of its statement, except when the last temporary value is bound to a name using let.
struct A(u8);
struct B(u8);
impl A
fn get_b(&mut self) -> Option<B>
Some(B(self.0))
fn a(v: u8) -> A
A(v)
// temporary A's lifetime is the end of the statement
// temporary B binds to a name so lives until the enclosing block
let b = a(1).get_b();
// temporary A's lifetime is the end of the statement
// temporary B's lifetime extends to the enclosing block,
// so that taking reference of temporary works similar as above
let b = &a(2).get_b();
If the temporary value is in an if condition, according to the reference, the lifetime is instead limited to the conditional expression.
// Both temporary A and temporary B drops before printing some
if a(3).get_b().unwrap().val <= 3
println!("some");
Now to the question:
If putting let in if condition, because of pattern matching, we are binding to the inner part of the temporary value. I'd expect the temporary value bound by let to be extended to the enclosing block, while other temporary values should still have a lifetime limited by the if condition.
(In this case actually everything is copied I would say even temporary B can be dropped, but that's a separate question.)
However, both temporaries' lifetimes are extended to the enclosing if block.
// Both temporary A and temporary B's lifetime are extended to the end of the enclosing block,
// which is the if statement
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
Should this be considered an inconsistency in Rust? Or am I misunderstanding and there is a consistent rule that can explain this behavior?
Full code example:
- playground
- The same thing implemented in C++ that matches my expectation
Note the output from Rust is
some 4
Drop B 4
Drop A 4
while the output from C++ is
Drop A 4
some 4
Drop B 4
I have read this Reddit thread and Rust issue, which I think is quite relevant, but I still can't find a clear set of lifetime rule that works for all the cases in Rust.
Update:
What I'm unclear about is why the temporary lifetime rule about if conditional expression does not apply to if let. I think the let Some(B(v @ 0...4)) = a(4).get_b() should be the conditional expression, and thus the temporary A's lifetime should be limited by that, rather than the entire if statement.
The behaviour of extending temporary B's lifetime to the entire if statement is expected, because that is borrowed by the pattern matching.
rust
2
you borrow&mut self, so I expect this result, try by consumeself=>get_b(self)
– Stargateur
Mar 22 at 5:11
@Stargateurget_bdoes borrow&mut self, but the return value doesn't contain a lifetime, so it doesn't need to "stay borrowed". I think what's happening here is the compiler considers the entireif letexpression "the current statement" (i.e., it doesn't work the same way aslet tmp = a(4).get_b(); if let Some(B(_)) = tmp ...which would have the same output as the similar C++ code.)
– trentcl
Mar 22 at 12:34
@trentcl The issue explain why, github.com/rust-lang/rust/issues/37612#issuecomment-304626464, pattern matching extend the borrow to the scope of the pattern matching.let b = a(4).get_b(); if let Some(B(v@ 0...4)) = b println!("some ", v);should work as expected.
– Stargateur
Mar 22 at 12:57
1
It's not that the borrow is extended, but the lifetime of the temporary is extended even though it isn't borrowed. At least that's my interpretation
– trentcl
Mar 22 at 13:20
@Stargateur ifget_bconsumesself, then that's a different situation. Temporary A will be dropped insideget_bbody because it is moved there. That's not the same effect as dropping at the end of the statement.
– Aetf
Mar 22 at 16:39
|
show 1 more comment
I'm trying to learn Rust's lifetime rules by comparing it to similar concepts in C++, which I'm more familiar with. Most of the time, my intuition works really well and I can make sense the rule. However, in the following case, I'm not sure if my understanding is correct or not.
In Rust, a temporary value's lifetime is the end of its statement, except when the last temporary value is bound to a name using let.
struct A(u8);
struct B(u8);
impl A
fn get_b(&mut self) -> Option<B>
Some(B(self.0))
fn a(v: u8) -> A
A(v)
// temporary A's lifetime is the end of the statement
// temporary B binds to a name so lives until the enclosing block
let b = a(1).get_b();
// temporary A's lifetime is the end of the statement
// temporary B's lifetime extends to the enclosing block,
// so that taking reference of temporary works similar as above
let b = &a(2).get_b();
If the temporary value is in an if condition, according to the reference, the lifetime is instead limited to the conditional expression.
// Both temporary A and temporary B drops before printing some
if a(3).get_b().unwrap().val <= 3
println!("some");
Now to the question:
If putting let in if condition, because of pattern matching, we are binding to the inner part of the temporary value. I'd expect the temporary value bound by let to be extended to the enclosing block, while other temporary values should still have a lifetime limited by the if condition.
(In this case actually everything is copied I would say even temporary B can be dropped, but that's a separate question.)
However, both temporaries' lifetimes are extended to the enclosing if block.
// Both temporary A and temporary B's lifetime are extended to the end of the enclosing block,
// which is the if statement
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
Should this be considered an inconsistency in Rust? Or am I misunderstanding and there is a consistent rule that can explain this behavior?
Full code example:
- playground
- The same thing implemented in C++ that matches my expectation
Note the output from Rust is
some 4
Drop B 4
Drop A 4
while the output from C++ is
Drop A 4
some 4
Drop B 4
I have read this Reddit thread and Rust issue, which I think is quite relevant, but I still can't find a clear set of lifetime rule that works for all the cases in Rust.
Update:
What I'm unclear about is why the temporary lifetime rule about if conditional expression does not apply to if let. I think the let Some(B(v @ 0...4)) = a(4).get_b() should be the conditional expression, and thus the temporary A's lifetime should be limited by that, rather than the entire if statement.
The behaviour of extending temporary B's lifetime to the entire if statement is expected, because that is borrowed by the pattern matching.
rust
I'm trying to learn Rust's lifetime rules by comparing it to similar concepts in C++, which I'm more familiar with. Most of the time, my intuition works really well and I can make sense the rule. However, in the following case, I'm not sure if my understanding is correct or not.
In Rust, a temporary value's lifetime is the end of its statement, except when the last temporary value is bound to a name using let.
struct A(u8);
struct B(u8);
impl A
fn get_b(&mut self) -> Option<B>
Some(B(self.0))
fn a(v: u8) -> A
A(v)
// temporary A's lifetime is the end of the statement
// temporary B binds to a name so lives until the enclosing block
let b = a(1).get_b();
// temporary A's lifetime is the end of the statement
// temporary B's lifetime extends to the enclosing block,
// so that taking reference of temporary works similar as above
let b = &a(2).get_b();
If the temporary value is in an if condition, according to the reference, the lifetime is instead limited to the conditional expression.
// Both temporary A and temporary B drops before printing some
if a(3).get_b().unwrap().val <= 3
println!("some");
Now to the question:
If putting let in if condition, because of pattern matching, we are binding to the inner part of the temporary value. I'd expect the temporary value bound by let to be extended to the enclosing block, while other temporary values should still have a lifetime limited by the if condition.
(In this case actually everything is copied I would say even temporary B can be dropped, but that's a separate question.)
However, both temporaries' lifetimes are extended to the enclosing if block.
// Both temporary A and temporary B's lifetime are extended to the end of the enclosing block,
// which is the if statement
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
Should this be considered an inconsistency in Rust? Or am I misunderstanding and there is a consistent rule that can explain this behavior?
Full code example:
- playground
- The same thing implemented in C++ that matches my expectation
Note the output from Rust is
some 4
Drop B 4
Drop A 4
while the output from C++ is
Drop A 4
some 4
Drop B 4
I have read this Reddit thread and Rust issue, which I think is quite relevant, but I still can't find a clear set of lifetime rule that works for all the cases in Rust.
Update:
What I'm unclear about is why the temporary lifetime rule about if conditional expression does not apply to if let. I think the let Some(B(v @ 0...4)) = a(4).get_b() should be the conditional expression, and thus the temporary A's lifetime should be limited by that, rather than the entire if statement.
The behaviour of extending temporary B's lifetime to the entire if statement is expected, because that is borrowed by the pattern matching.
rust
rust
edited Mar 22 at 17:06
Aetf
asked Mar 22 at 2:45
AetfAetf
4619
4619
2
you borrow&mut self, so I expect this result, try by consumeself=>get_b(self)
– Stargateur
Mar 22 at 5:11
@Stargateurget_bdoes borrow&mut self, but the return value doesn't contain a lifetime, so it doesn't need to "stay borrowed". I think what's happening here is the compiler considers the entireif letexpression "the current statement" (i.e., it doesn't work the same way aslet tmp = a(4).get_b(); if let Some(B(_)) = tmp ...which would have the same output as the similar C++ code.)
– trentcl
Mar 22 at 12:34
@trentcl The issue explain why, github.com/rust-lang/rust/issues/37612#issuecomment-304626464, pattern matching extend the borrow to the scope of the pattern matching.let b = a(4).get_b(); if let Some(B(v@ 0...4)) = b println!("some ", v);should work as expected.
– Stargateur
Mar 22 at 12:57
1
It's not that the borrow is extended, but the lifetime of the temporary is extended even though it isn't borrowed. At least that's my interpretation
– trentcl
Mar 22 at 13:20
@Stargateur ifget_bconsumesself, then that's a different situation. Temporary A will be dropped insideget_bbody because it is moved there. That's not the same effect as dropping at the end of the statement.
– Aetf
Mar 22 at 16:39
|
show 1 more comment
2
you borrow&mut self, so I expect this result, try by consumeself=>get_b(self)
– Stargateur
Mar 22 at 5:11
@Stargateurget_bdoes borrow&mut self, but the return value doesn't contain a lifetime, so it doesn't need to "stay borrowed". I think what's happening here is the compiler considers the entireif letexpression "the current statement" (i.e., it doesn't work the same way aslet tmp = a(4).get_b(); if let Some(B(_)) = tmp ...which would have the same output as the similar C++ code.)
– trentcl
Mar 22 at 12:34
@trentcl The issue explain why, github.com/rust-lang/rust/issues/37612#issuecomment-304626464, pattern matching extend the borrow to the scope of the pattern matching.let b = a(4).get_b(); if let Some(B(v@ 0...4)) = b println!("some ", v);should work as expected.
– Stargateur
Mar 22 at 12:57
1
It's not that the borrow is extended, but the lifetime of the temporary is extended even though it isn't borrowed. At least that's my interpretation
– trentcl
Mar 22 at 13:20
@Stargateur ifget_bconsumesself, then that's a different situation. Temporary A will be dropped insideget_bbody because it is moved there. That's not the same effect as dropping at the end of the statement.
– Aetf
Mar 22 at 16:39
2
2
you borrow
&mut self, so I expect this result, try by consume self => get_b(self)– Stargateur
Mar 22 at 5:11
you borrow
&mut self, so I expect this result, try by consume self => get_b(self)– Stargateur
Mar 22 at 5:11
@Stargateur
get_b does borrow &mut self, but the return value doesn't contain a lifetime, so it doesn't need to "stay borrowed". I think what's happening here is the compiler considers the entire if let expression "the current statement" (i.e., it doesn't work the same way as let tmp = a(4).get_b(); if let Some(B(_)) = tmp ... which would have the same output as the similar C++ code.)– trentcl
Mar 22 at 12:34
@Stargateur
get_b does borrow &mut self, but the return value doesn't contain a lifetime, so it doesn't need to "stay borrowed". I think what's happening here is the compiler considers the entire if let expression "the current statement" (i.e., it doesn't work the same way as let tmp = a(4).get_b(); if let Some(B(_)) = tmp ... which would have the same output as the similar C++ code.)– trentcl
Mar 22 at 12:34
@trentcl The issue explain why, github.com/rust-lang/rust/issues/37612#issuecomment-304626464, pattern matching extend the borrow to the scope of the pattern matching.
let b = a(4).get_b(); if let Some(B(v@ 0...4)) = b println!("some ", v); should work as expected.– Stargateur
Mar 22 at 12:57
@trentcl The issue explain why, github.com/rust-lang/rust/issues/37612#issuecomment-304626464, pattern matching extend the borrow to the scope of the pattern matching.
let b = a(4).get_b(); if let Some(B(v@ 0...4)) = b println!("some ", v); should work as expected.– Stargateur
Mar 22 at 12:57
1
1
It's not that the borrow is extended, but the lifetime of the temporary is extended even though it isn't borrowed. At least that's my interpretation
– trentcl
Mar 22 at 13:20
It's not that the borrow is extended, but the lifetime of the temporary is extended even though it isn't borrowed. At least that's my interpretation
– trentcl
Mar 22 at 13:20
@Stargateur if
get_b consumes self, then that's a different situation. Temporary A will be dropped inside get_b body because it is moved there. That's not the same effect as dropping at the end of the statement.– Aetf
Mar 22 at 16:39
@Stargateur if
get_b consumes self, then that's a different situation. Temporary A will be dropped inside get_b body because it is moved there. That's not the same effect as dropping at the end of the statement.– Aetf
Mar 22 at 16:39
|
show 1 more comment
1 Answer
1
active
oldest
votes
An if let construct is just syntactic sugar for a match construct. let Some(B(v @ 0...4)) = a(4).get_b() is not a conditional used in a regular if expression, because it is not an expression that evaluates to bool. Given your example:
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
It will behave exactly the same as this example. No exceptions. if let is rewritten into match before the type or borrow checkers are even run.
match a(4).get_b()
Some(B(v @ 0...4)) =>
println!("some ", v);
_ =>
Temporaries live as long as they do in match blocks because they sometimes come in handy. Like if your last function was fn get_b(&mut self) -> Option<&B>, and if the temporary didn't live for the entire match block, then it wouldn't pass borrowck.
If conditionals don't follow the same rule because it's impossible for the last function call in an if conditional to hold a reference to anything. They have to evaluate to a plain bool.
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55292164%2frust-temporary-variable-lifetime-in-method-chaining%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
An if let construct is just syntactic sugar for a match construct. let Some(B(v @ 0...4)) = a(4).get_b() is not a conditional used in a regular if expression, because it is not an expression that evaluates to bool. Given your example:
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
It will behave exactly the same as this example. No exceptions. if let is rewritten into match before the type or borrow checkers are even run.
match a(4).get_b()
Some(B(v @ 0...4)) =>
println!("some ", v);
_ =>
Temporaries live as long as they do in match blocks because they sometimes come in handy. Like if your last function was fn get_b(&mut self) -> Option<&B>, and if the temporary didn't live for the entire match block, then it wouldn't pass borrowck.
If conditionals don't follow the same rule because it's impossible for the last function call in an if conditional to hold a reference to anything. They have to evaluate to a plain bool.
add a comment |
An if let construct is just syntactic sugar for a match construct. let Some(B(v @ 0...4)) = a(4).get_b() is not a conditional used in a regular if expression, because it is not an expression that evaluates to bool. Given your example:
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
It will behave exactly the same as this example. No exceptions. if let is rewritten into match before the type or borrow checkers are even run.
match a(4).get_b()
Some(B(v @ 0...4)) =>
println!("some ", v);
_ =>
Temporaries live as long as they do in match blocks because they sometimes come in handy. Like if your last function was fn get_b(&mut self) -> Option<&B>, and if the temporary didn't live for the entire match block, then it wouldn't pass borrowck.
If conditionals don't follow the same rule because it's impossible for the last function call in an if conditional to hold a reference to anything. They have to evaluate to a plain bool.
add a comment |
An if let construct is just syntactic sugar for a match construct. let Some(B(v @ 0...4)) = a(4).get_b() is not a conditional used in a regular if expression, because it is not an expression that evaluates to bool. Given your example:
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
It will behave exactly the same as this example. No exceptions. if let is rewritten into match before the type or borrow checkers are even run.
match a(4).get_b()
Some(B(v @ 0...4)) =>
println!("some ", v);
_ =>
Temporaries live as long as they do in match blocks because they sometimes come in handy. Like if your last function was fn get_b(&mut self) -> Option<&B>, and if the temporary didn't live for the entire match block, then it wouldn't pass borrowck.
If conditionals don't follow the same rule because it's impossible for the last function call in an if conditional to hold a reference to anything. They have to evaluate to a plain bool.
An if let construct is just syntactic sugar for a match construct. let Some(B(v @ 0...4)) = a(4).get_b() is not a conditional used in a regular if expression, because it is not an expression that evaluates to bool. Given your example:
if let Some(B(v @ 0...4)) = a(4).get_b()
println!("some ", v);
It will behave exactly the same as this example. No exceptions. if let is rewritten into match before the type or borrow checkers are even run.
match a(4).get_b()
Some(B(v @ 0...4)) =>
println!("some ", v);
_ =>
Temporaries live as long as they do in match blocks because they sometimes come in handy. Like if your last function was fn get_b(&mut self) -> Option<&B>, and if the temporary didn't live for the entire match block, then it wouldn't pass borrowck.
If conditionals don't follow the same rule because it's impossible for the last function call in an if conditional to hold a reference to anything. They have to evaluate to a plain bool.
answered Mar 22 at 19:18
notriddlenotriddle
45338
45338
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55292164%2frust-temporary-variable-lifetime-in-method-chaining%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
2
you borrow
&mut self, so I expect this result, try by consumeself=>get_b(self)– Stargateur
Mar 22 at 5:11
@Stargateur
get_bdoes borrow&mut self, but the return value doesn't contain a lifetime, so it doesn't need to "stay borrowed". I think what's happening here is the compiler considers the entireif letexpression "the current statement" (i.e., it doesn't work the same way aslet tmp = a(4).get_b(); if let Some(B(_)) = tmp ...which would have the same output as the similar C++ code.)– trentcl
Mar 22 at 12:34
@trentcl The issue explain why, github.com/rust-lang/rust/issues/37612#issuecomment-304626464, pattern matching extend the borrow to the scope of the pattern matching.
let b = a(4).get_b(); if let Some(B(v@ 0...4)) = b println!("some ", v);should work as expected.– Stargateur
Mar 22 at 12:57
1
It's not that the borrow is extended, but the lifetime of the temporary is extended even though it isn't borrowed. At least that's my interpretation
– trentcl
Mar 22 at 13:20
@Stargateur if
get_bconsumesself, then that's a different situation. Temporary A will be dropped insideget_bbody because it is moved there. That's not the same effect as dropping at the end of the statement.– Aetf
Mar 22 at 16:39