From 242118b0a4d3f283579a22cc39b89691746e5200 Mon Sep 17 00:00:00 2001 From: Pieter Penninckx Date: Fri, 4 Aug 2017 16:38:16 +0200 Subject: [PATCH 1/3] Document lifetime of temporaries in condition expression of if-expr Explain that temporaries created in the condition expression of an if or if/else are dropped immediately after the condition expression. --- src/expressions.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 96d2d2162..e97269e7b 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -88,9 +88,20 @@ created and used instead. 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. -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` +A first exception is when a temporary value is created in the +condition expression of an `if` or an `if`/`else` expression. +In this case, the lifetime ends right after the condition expression. + +Here is an example: + +- `let x = if foo(&temp()) {bar()} else {bas()};`. The expression `temp()` is + an rvalue. As the temporary is created in the condition expression + of an `if`/`else`, it will be freed at the end of the condition expression + (in this example before the call to `bar` or `bas` is made). + +Another exception is when a temporary rvalue is being created that is assigned +into a `let` declaration. In this case the temporary is created with the +lifetime of the enclosing block, 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 From 9b340a1934027699e736bf7868dc10f7c5996727 Mon Sep 17 00:00:00 2001 From: Pieter Penninckx Date: Sat, 5 Aug 2017 13:14:23 +0200 Subject: [PATCH 2/3] Document lifetimes of temporaries in while-expression Explain that temporaries created in the loop conditional expression of a while expression are freed immediately after the loop conditional expression. --- src/expressions.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index e97269e7b..1c6eade92 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -89,15 +89,21 @@ innermost enclosing statement; the tail expression of a block is considered part of the statement that encloses the block. A first exception is when a temporary value is created in the -condition expression of an `if` or an `if`/`else` expression. -In this case, the lifetime ends right after the condition expression. +condition expression of an `if` or an `if`/`else` expression or in the +loop conditional expression of a `while` expression. +In this case, the lifetime ends right after the condition expression or the +loop conditional expression. -Here is an example: +Here are some examples: -- `let x = if foo(&temp()) {bar()} else {bas()};`. The expression `temp()` is +- `let x = if foo(&temp()) {bar()} else {baz()}`. The expression `temp()` is an rvalue. As the temporary is created in the condition expression of an `if`/`else`, it will be freed at the end of the condition expression - (in this example before the call to `bar` or `bas` is made). + (in this example before the call to `bar` or `baz` is made). +- `while foo(&temp()) {bar();}`. The temporary containing the return value from + the call to `temp()` is created in the loop conditional expression. Hence it + will be freed at the end of the loop conditional expression (in this example + before the call to `bar` if the loop body is executed). Another exception is when a temporary rvalue is being created that is assigned into a `let` declaration. In this case the temporary is created with the From feed47941d5e62d51afb29b185123c5354c69a55 Mon Sep 17 00:00:00 2001 From: Pieter Penninckx Date: Sun, 13 Aug 2017 16:21:47 +0200 Subject: [PATCH 3/3] Make dropping of temporaries in conditionals part of the rule Reformulate text so that dropping of temporaries created in condition expression of an `if` or `if`/`else` or in the loop conditional expression of a `while` is now part of the rule, not an exception. Revert the paragraph concerning the `let` expression to its original form. Move examples. Include an example of a temporary without borrowing. --- src/expressions.md | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 1c6eade92..0aad767c5 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -84,30 +84,17 @@ The following expressions can create mutable lvalues: ### Temporary lifetimes When using an rvalue in most lvalue contexts, a temporary unnamed lvalue is -created and used instead. 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. +created and used instead. The lifetime of temporary values is typically -A first exception is when a temporary value is created in the -condition expression of an `if` or an `if`/`else` expression or in the -loop conditional expression of a `while` expression. -In this case, the lifetime ends right after the condition expression or the -loop conditional expression. +- 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. -Here are some examples: - -- `let x = if foo(&temp()) {bar()} else {baz()}`. The expression `temp()` is - an rvalue. As the temporary is created in the condition expression - of an `if`/`else`, it will be freed at the end of the condition expression - (in this example before the call to `bar` or `baz` is made). -- `while foo(&temp()) {bar();}`. The temporary containing the return value from - the call to `temp()` is created in the loop conditional expression. Hence it - will be freed at the end of the loop conditional expression (in this example - before the call to `bar` if the loop body is executed). - -Another exception is when a temporary rvalue is being created that is assigned -into a `let` declaration. In this case the temporary is created with the -lifetime of the enclosing block, as using the enclosing statement (the `let` +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 @@ -124,6 +111,18 @@ Here are some examples: method-call. Here we are assuming that `foo()` is an `&self` method defined in some trait, say `Foo`. In other words, the expression `temp().foo()` is equivalent to `Foo::foo(&temp())`. +- `let x = if foo(&temp()) {bar()} else {baz()};`. The expression `temp()` is + an rvalue. As the temporary is created in the condition expression + of an `if`/`else`, it will be freed at the end of the condition expression + (in this example before the call to `bar` or `baz` is made). +- `let x = if temp().must_run_bar {bar()} else {baz()};`. + Here we assume the type of `temp()` is a struct with a boolean field + `must_run_bar`. As the previous example, the temporary corresponding to + `temp()` will be freed at the end of the condition expression. +- `while foo(&temp()) {bar();}`. The temporary containing the return value from + the call to `temp()` is created in the loop conditional expression. Hence it + will be freed at the end of the loop conditional expression (in this example + before the call to `bar` if the loop body is executed). - `let x = &temp()`. Here, the same temporary is being assigned into `x`, rather than being passed as a parameter, and hence the temporary's lifetime is considered to be the enclosing block.