What is the scope of unnamed values?












1














When do unnamed values go out of scope, when is the value dropped?



I'm looking for an answer based on official docs, not based on experiments.



Example 1:



f(foo().bar());


Example 2:



match foo().bar() {
// ...
}


If bar is fn bar(self) -> ... it takes ownership of the passed value, and it is dropped as usual, but what happens if bar borrows, i.e. fn bar(&self) -> ...? Does it matter whether the result of bar depends on the lifetime of &self?



That is, foo could be returning a MutexGuard; it is essential to know when the guard is dropped (and the mutex is unlocked).



The experimental method shows that the unnamed value is dropped after the statement it is created in is "finished"; to force the "early" drop a let statement is required.



Playground



#[derive(Debug)]
pub struct Foo;
pub fn foo() -> Foo {
println!("foo()");
Foo
}
impl Foo {
pub fn bar(&self) {
}
}
impl Drop for Foo {
fn drop(&mut self) {
println!("Foo::drop()");
}
}

fn main() {
println!("--- scope test start");
println!("value: {:?}", foo().bar());
println!("--- end");

println!("--- scope test start");
match foo().bar() {
v => println!("value: {:?}", v),
}
println!("--- end");

println!("--- scope test start");
let v = foo().bar();
println!("value: {:?}", v);
println!("--- end");
}


prints:



--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
Foo::drop()
value: ()
--- end









share|improve this question
























  • Can you clarify what you mean by "to force the "early" drop"?
    – Shepmaster
    Oct 31 '17 at 21:03










  • @Shepmaster Well, with let the drop happens as expected, but compared to the other constructions Foo is dropped "early".
    – Stefan
    Oct 31 '17 at 21:13
















1














When do unnamed values go out of scope, when is the value dropped?



I'm looking for an answer based on official docs, not based on experiments.



Example 1:



f(foo().bar());


Example 2:



match foo().bar() {
// ...
}


If bar is fn bar(self) -> ... it takes ownership of the passed value, and it is dropped as usual, but what happens if bar borrows, i.e. fn bar(&self) -> ...? Does it matter whether the result of bar depends on the lifetime of &self?



That is, foo could be returning a MutexGuard; it is essential to know when the guard is dropped (and the mutex is unlocked).



The experimental method shows that the unnamed value is dropped after the statement it is created in is "finished"; to force the "early" drop a let statement is required.



Playground



#[derive(Debug)]
pub struct Foo;
pub fn foo() -> Foo {
println!("foo()");
Foo
}
impl Foo {
pub fn bar(&self) {
}
}
impl Drop for Foo {
fn drop(&mut self) {
println!("Foo::drop()");
}
}

fn main() {
println!("--- scope test start");
println!("value: {:?}", foo().bar());
println!("--- end");

println!("--- scope test start");
match foo().bar() {
v => println!("value: {:?}", v),
}
println!("--- end");

println!("--- scope test start");
let v = foo().bar();
println!("value: {:?}", v);
println!("--- end");
}


prints:



--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
Foo::drop()
value: ()
--- end









share|improve this question
























  • Can you clarify what you mean by "to force the "early" drop"?
    – Shepmaster
    Oct 31 '17 at 21:03










  • @Shepmaster Well, with let the drop happens as expected, but compared to the other constructions Foo is dropped "early".
    – Stefan
    Oct 31 '17 at 21:13














1












1








1







When do unnamed values go out of scope, when is the value dropped?



I'm looking for an answer based on official docs, not based on experiments.



Example 1:



f(foo().bar());


Example 2:



match foo().bar() {
// ...
}


If bar is fn bar(self) -> ... it takes ownership of the passed value, and it is dropped as usual, but what happens if bar borrows, i.e. fn bar(&self) -> ...? Does it matter whether the result of bar depends on the lifetime of &self?



That is, foo could be returning a MutexGuard; it is essential to know when the guard is dropped (and the mutex is unlocked).



The experimental method shows that the unnamed value is dropped after the statement it is created in is "finished"; to force the "early" drop a let statement is required.



Playground



#[derive(Debug)]
pub struct Foo;
pub fn foo() -> Foo {
println!("foo()");
Foo
}
impl Foo {
pub fn bar(&self) {
}
}
impl Drop for Foo {
fn drop(&mut self) {
println!("Foo::drop()");
}
}

fn main() {
println!("--- scope test start");
println!("value: {:?}", foo().bar());
println!("--- end");

println!("--- scope test start");
match foo().bar() {
v => println!("value: {:?}", v),
}
println!("--- end");

println!("--- scope test start");
let v = foo().bar();
println!("value: {:?}", v);
println!("--- end");
}


prints:



--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
Foo::drop()
value: ()
--- end









share|improve this question















When do unnamed values go out of scope, when is the value dropped?



I'm looking for an answer based on official docs, not based on experiments.



Example 1:



f(foo().bar());


Example 2:



match foo().bar() {
// ...
}


If bar is fn bar(self) -> ... it takes ownership of the passed value, and it is dropped as usual, but what happens if bar borrows, i.e. fn bar(&self) -> ...? Does it matter whether the result of bar depends on the lifetime of &self?



That is, foo could be returning a MutexGuard; it is essential to know when the guard is dropped (and the mutex is unlocked).



The experimental method shows that the unnamed value is dropped after the statement it is created in is "finished"; to force the "early" drop a let statement is required.



Playground



#[derive(Debug)]
pub struct Foo;
pub fn foo() -> Foo {
println!("foo()");
Foo
}
impl Foo {
pub fn bar(&self) {
}
}
impl Drop for Foo {
fn drop(&mut self) {
println!("Foo::drop()");
}
}

fn main() {
println!("--- scope test start");
println!("value: {:?}", foo().bar());
println!("--- end");

println!("--- scope test start");
match foo().bar() {
v => println!("value: {:?}", v),
}
println!("--- end");

println!("--- scope test start");
let v = foo().bar();
println!("value: {:?}", v);
println!("--- end");
}


prints:



--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
Foo::drop()
value: ()
--- end






rust






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 31 '17 at 21:03









Shepmaster

148k12283418




148k12283418










asked Oct 31 '17 at 20:58









Stefan

3,61911129




3,61911129












  • Can you clarify what you mean by "to force the "early" drop"?
    – Shepmaster
    Oct 31 '17 at 21:03










  • @Shepmaster Well, with let the drop happens as expected, but compared to the other constructions Foo is dropped "early".
    – Stefan
    Oct 31 '17 at 21:13


















  • Can you clarify what you mean by "to force the "early" drop"?
    – Shepmaster
    Oct 31 '17 at 21:03










  • @Shepmaster Well, with let the drop happens as expected, but compared to the other constructions Foo is dropped "early".
    – Stefan
    Oct 31 '17 at 21:13
















Can you clarify what you mean by "to force the "early" drop"?
– Shepmaster
Oct 31 '17 at 21:03




Can you clarify what you mean by "to force the "early" drop"?
– Shepmaster
Oct 31 '17 at 21:03












@Shepmaster Well, with let the drop happens as expected, but compared to the other constructions Foo is dropped "early".
– Stefan
Oct 31 '17 at 21:13




@Shepmaster Well, with let the drop happens as expected, but compared to the other constructions Foo is dropped "early".
– Stefan
Oct 31 '17 at 21:13












1 Answer
1






active

oldest

votes


















2














From the reference:




When using an rvalue in most lvalue contexts, a temporary unnamed
lvalue is created and used instead, if not promoted to 'static.
Promotion of an rvalue expression to a 'static slot occurs when the
expression could be written in a constant, borrowed, and dereferencing
that borrow where the expression was the originally written, without
changing the runtime behavior. That is, the promoted expression can be
evaluated at compile-time and the resulting value does not contain
interior mutability or destructors (these properties are determined
based on the value where possible, e.g. &None always has the type
&'static Option<_>, as it contains nothing disallowed). Otherwise, the
lifetime of temporary values is typically




  • the innermost enclosing statement; the tail expression of a block is
    considered part of the statement that encloses the block, or


  • the
    condition expression or the loop conditional expression if the
    temporary is created in the condition expression of an if or an
    if/else or in the loop conditional expression of a while expression.



When a temporary rvalue is being created that is assigned into a let
declaration, however, the temporary is created with the lifetime of
the enclosing block instead, as using the enclosing statement (the let
declaration) would be a guaranteed error (since a pointer to the
temporary would be stored into a variable, but the temporary would be
freed before the variable could be used). The compiler uses simple
syntactic rules to decide which values are being assigned into a let
binding, and therefore deserve a longer temporary lifetime.




The reference then has examples of these rules.






share|improve this answer























    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%2f47044453%2fwhat-is-the-scope-of-unnamed-values%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









    2














    From the reference:




    When using an rvalue in most lvalue contexts, a temporary unnamed
    lvalue is created and used instead, if not promoted to 'static.
    Promotion of an rvalue expression to a 'static slot occurs when the
    expression could be written in a constant, borrowed, and dereferencing
    that borrow where the expression was the originally written, without
    changing the runtime behavior. That is, the promoted expression can be
    evaluated at compile-time and the resulting value does not contain
    interior mutability or destructors (these properties are determined
    based on the value where possible, e.g. &None always has the type
    &'static Option<_>, as it contains nothing disallowed). Otherwise, the
    lifetime of temporary values is typically




    • the innermost enclosing statement; the tail expression of a block is
      considered part of the statement that encloses the block, or


    • the
      condition expression or the loop conditional expression if the
      temporary is created in the condition expression of an if or an
      if/else or in the loop conditional expression of a while expression.



    When a temporary rvalue is being created that is assigned into a let
    declaration, however, the temporary is created with the lifetime of
    the enclosing block instead, as using the enclosing statement (the let
    declaration) would be a guaranteed error (since a pointer to the
    temporary would be stored into a variable, but the temporary would be
    freed before the variable could be used). The compiler uses simple
    syntactic rules to decide which values are being assigned into a let
    binding, and therefore deserve a longer temporary lifetime.




    The reference then has examples of these rules.






    share|improve this answer




























      2














      From the reference:




      When using an rvalue in most lvalue contexts, a temporary unnamed
      lvalue is created and used instead, if not promoted to 'static.
      Promotion of an rvalue expression to a 'static slot occurs when the
      expression could be written in a constant, borrowed, and dereferencing
      that borrow where the expression was the originally written, without
      changing the runtime behavior. That is, the promoted expression can be
      evaluated at compile-time and the resulting value does not contain
      interior mutability or destructors (these properties are determined
      based on the value where possible, e.g. &None always has the type
      &'static Option<_>, as it contains nothing disallowed). Otherwise, the
      lifetime of temporary values is typically




      • the innermost enclosing statement; the tail expression of a block is
        considered part of the statement that encloses the block, or


      • the
        condition expression or the loop conditional expression if the
        temporary is created in the condition expression of an if or an
        if/else or in the loop conditional expression of a while expression.



      When a temporary rvalue is being created that is assigned into a let
      declaration, however, the temporary is created with the lifetime of
      the enclosing block instead, as using the enclosing statement (the let
      declaration) would be a guaranteed error (since a pointer to the
      temporary would be stored into a variable, but the temporary would be
      freed before the variable could be used). The compiler uses simple
      syntactic rules to decide which values are being assigned into a let
      binding, and therefore deserve a longer temporary lifetime.




      The reference then has examples of these rules.






      share|improve this answer


























        2












        2








        2






        From the reference:




        When using an rvalue in most lvalue contexts, a temporary unnamed
        lvalue is created and used instead, if not promoted to 'static.
        Promotion of an rvalue expression to a 'static slot occurs when the
        expression could be written in a constant, borrowed, and dereferencing
        that borrow where the expression was the originally written, without
        changing the runtime behavior. That is, the promoted expression can be
        evaluated at compile-time and the resulting value does not contain
        interior mutability or destructors (these properties are determined
        based on the value where possible, e.g. &None always has the type
        &'static Option<_>, as it contains nothing disallowed). Otherwise, the
        lifetime of temporary values is typically




        • the innermost enclosing statement; the tail expression of a block is
          considered part of the statement that encloses the block, or


        • the
          condition expression or the loop conditional expression if the
          temporary is created in the condition expression of an if or an
          if/else or in the loop conditional expression of a while expression.



        When a temporary rvalue is being created that is assigned into a let
        declaration, however, the temporary is created with the lifetime of
        the enclosing block instead, as using the enclosing statement (the let
        declaration) would be a guaranteed error (since a pointer to the
        temporary would be stored into a variable, but the temporary would be
        freed before the variable could be used). The compiler uses simple
        syntactic rules to decide which values are being assigned into a let
        binding, and therefore deserve a longer temporary lifetime.




        The reference then has examples of these rules.






        share|improve this answer














        From the reference:




        When using an rvalue in most lvalue contexts, a temporary unnamed
        lvalue is created and used instead, if not promoted to 'static.
        Promotion of an rvalue expression to a 'static slot occurs when the
        expression could be written in a constant, borrowed, and dereferencing
        that borrow where the expression was the originally written, without
        changing the runtime behavior. That is, the promoted expression can be
        evaluated at compile-time and the resulting value does not contain
        interior mutability or destructors (these properties are determined
        based on the value where possible, e.g. &None always has the type
        &'static Option<_>, as it contains nothing disallowed). Otherwise, the
        lifetime of temporary values is typically




        • the innermost enclosing statement; the tail expression of a block is
          considered part of the statement that encloses the block, or


        • the
          condition expression or the loop conditional expression if the
          temporary is created in the condition expression of an if or an
          if/else or in the loop conditional expression of a while expression.



        When a temporary rvalue is being created that is assigned into a let
        declaration, however, the temporary is created with the lifetime of
        the enclosing block instead, as using the enclosing statement (the let
        declaration) would be a guaranteed error (since a pointer to the
        temporary would be stored into a variable, but the temporary would be
        freed before the variable could be used). The compiler uses simple
        syntactic rules to decide which values are being assigned into a let
        binding, and therefore deserve a longer temporary lifetime.




        The reference then has examples of these rules.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Oct 31 '17 at 21:38

























        answered Oct 31 '17 at 21:08









        Shepmaster

        148k12283418




        148k12283418






























            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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%2f47044453%2fwhat-is-the-scope-of-unnamed-values%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

            Berounka

            Different font size/position of beamer's navigation symbols template's content depending on regular/plain...

            Sphinx de Gizeh