-
Notifications
You must be signed in to change notification settings - Fork 488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Expressions rewrite #13
[WIP] Expressions rewrite #13
Conversation
* Add examples for methods * Show the syntax for calling a struct field * Explain the function call syntax * Mention `Fn` traits * Move lambda section * Lambdas have unique types * `move` is part of the lambda expression according to libsyntax * Explain that `move` can extend the lifetime of the closure * Use closure, except when followed by 'expression' * Closure traits depend on how captures are used, not on how they are captured
* Parameters are patterns, not idents. * Make it clear that inference can be done on just some of the parameters
* Explain what arrays expressions do. * `static`s aren't constant expressions. * Explain `Copy` requirement.
* Specify how overloading is done. * Indices must be of type `usize`.
* Explained `std::ops::Neg`. * Hopefully made it clearer how `Deref` works * Explained `std::ops::Not`. * Say that `&mut` can't be applied to everything.
* Built in operators don't use traits. * Explain that the type of right shift depends on the type.
* Explain overloading
* Add unary operators * Show the correct associativity
* Use 'then' instead of and. * State that all loops return `()`. * Add some more examples. * Don't use 'identical' for things that aren't. * Make the definition of `if let` and `while let` clearer. * State that struct expressions can't be used in control flow expressions.
Add operator examples Mention `if let` and `while let` as more places where struct literals can't be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some questions I had while writing this. (Outdated comments are still sometimes relevant)
src/expressions.md
Outdated
is typically the innermost enclosing statement; the tail expression of | ||
a block is considered part of the statement that encloses the block. | ||
When an rvalue is used in an lvalue context, a temporary un-named lvalue is | ||
created and used instead. The lifetime of temporary values is typically the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't true for the LHS of =
.
1. Trait methods with receiver of type `&A`. | ||
1. Trait methods with receiver of type `&mut A`. | ||
1. If it's possible, Rust will then repeat steps 1-5 with | ||
`<A as std::ops::Deref>::Target`, and insert a dereference operator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this clear and correct? Is it what is intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some other explanations to look at
typeck - suggests there is also 'unsizing' happening.
stack overflow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might not be perfect, but it's also not incorrect; we may want to elaborate later, but I don't think it needs to block this PR
src/expressions.md
Outdated
## Lambda expressions | ||
|
||
A _lambda expression_ (sometimes called an "anonymous function expression") | ||
defines a closure and denotes it as a value, in a single expression. A lambda |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am I using 'lambda expression' and 'closure' correctly? Is there even a (single) correct choice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally would always refer to these as "closures" everywhere. Rust only has "closures" and "functions", it does not have anonymous functions nor named closures. "lambda" adds another term for no real gain, IMO.
src/expressions.md
Outdated
Operators are defined for built in types by the Rust language. Operators will | ||
panic when they overflow when compiled in debug mode. Many of the following | ||
operators can be overloaded using traits in `std::ops` or `std::cmp`. Note that | ||
the traits in `std::cmp` are used more generally to show how a type may be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, and other places, should I link to std
documentation?
Should I mention that these are also in core
?
src/expressions.md
Outdated
assigned to. Dereferencing a raw pointer requires `unsafe`. On non-pointer | ||
types `*x` is equivalent to `*std::ops::Deref::deref(&x)` or | ||
`*std::ops::Deref::deref_mut(&mut x)` depending on whether the rquired | ||
lvalue has to be mutable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should deref coercions be explained here, or in the Deref
chapter, or elsewhere?
src/expressions.md
Outdated
and written in postfix notation. | ||
: Propagating errors if applied to `Err(_)` and unwrapping if applied to | ||
`Ok(_)`. Only works on the `Result<T, E>` type, and written in postfix | ||
notation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestions on how to improve this are welcome.
src/expressions.md
Outdated
| `<<` | Left Shift | | | `std::ops::Shl` | | ||
| `>>` | Right Shift* | | | `std::ops::Shr` | | ||
|
||
\* Arithmetic right shift on signed integers, Logical right shift on unsigned integers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tables for operators, 👍/👎?
src/expressions.md
Outdated
the borrow expires. If the `&` or `&mut` operators are applied to an | ||
rvalue, a temporary value is created; the lifetime of this temporary value | ||
is defined by [syntactic rules](#temporary-lifetimes). `&mut` may only be | ||
applied to `lvalues` that can be mutated. These operators cannot be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to write 'mutable lvalue' so much, but is that the proper way to say what I mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly relevant part of typeck.
src/expressions.md
Outdated
```rust | ||
let x = false || true; // true | ||
let y = false && panic!(); // false, doesn't evaluate `panic!()` | ||
``` | ||
|
||
### Type cast expressions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I copy the (old) book explanation for all of the as
casts here, or somewhere else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here seems good
"Smaller" | ||
}; | ||
assert_eq!(y, "Bigger"); | ||
``` | ||
|
||
## `match` expressions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can patterns be moved to their own section?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems good to me
* Mutable lvalues * Implicit borrows * Overflow
src/expressions.md
Outdated
a block is considered part of the statement that encloses the block. | ||
When an lvalue is evaluated in an _rvalue context_, it denotes the value held | ||
_in_ that memory location. If value is of a type that implements `Copy`, then | ||
the value will be copied. In other situations if the type of the value is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few places I'm using 'other' to mean 'all other' or 'otherwise'. Any suggestions for an alternative wording would also be appreciated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why you don't like 'other' here? Seems fine to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is that could be interpreted as 'some other'.
Hey @matthewjasper Sorry this has taken me so long to look at, big PRs are tough. I will try to do so this week. |
I understand that, feel free to only review some of this or ask me for things to make this easier to review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whew! thank you so much for all of this, and sorry it took me so long.
I'm broadly in favor of merging this, but there's some formatting nits, and the lambda thing.
src/expressions.md
Outdated
a block is considered part of the statement that encloses the block. | ||
When an lvalue is evaluated in an _rvalue context_, it denotes the value held | ||
_in_ that memory location. If value is of a type that implements `Copy`, then | ||
the value will be copied. In other situations if the type of the value is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why you don't like 'other' here? Seems fine to me.
src/expressions.md
Outdated
the value will be copied. In other situations if the type of the value is | ||
[`Sized`](the-sized-trait.html) it may be possible to move the value. Only the | ||
following lvalues may be moved out of: | ||
* [Variables](#variables.html) which are not currently borrowed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a newline above this? I like to let it breathe a bit 😄
src/expressions.md
Outdated
``` | ||
|
||
Implicit borrows may be taken in the following expressions: | ||
* Left operand in [method-call expressions](#method-call-expressions). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
src/expressions.md
Outdated
|
||
When resolving method calls on an expression of type `A`, Rust will use the | ||
following order: | ||
1. Inherent methods, with receiver of type `A`, `&A`, `&mut A`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
src/expressions.md
Outdated
|
||
Note: that in steps 1-4 the receiver is used, not the type of `Self`, which may | ||
not be the same as `A`. For example | ||
```rust |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
src/expressions.md
Outdated
* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast* | ||
* Same concerns as with pointer to address casts | ||
|
||
TODO: Explain the semantics of these. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing so doesn't block this PR, IMHO; the reference is still incomplete.
src/expressions.md
Outdated
present, then labelled `break` and `continue` expressions nested within this | ||
loop may exit out of this loop or return control to its head. See [break | ||
expressions](#break-expressions) and [continue | ||
expressions](#continue-expressions). Any `loop` expression has value `()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not true anymore now that that is being stabilized
src/expressions.md
Outdated
conditional expression evaluates to `false`, the `while` expression completes. | ||
|
||
An example: | ||
An example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this space?
"Smaller" | ||
}; | ||
assert_eq!(y, "Bigger"); | ||
``` | ||
|
||
## `match` expressions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems good to me
src/expressions.md
Outdated
pattern, an `=` and an expression. If the value of the expression on the right | ||
hand side of the `=` matches the pattern, the loop body block executes then | ||
control returns to the pattern matching statement. Otherwise, the while | ||
expression completes. Like `while` loops, `while let` loops evaluate to `()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same issue here wrt new features
2e8f7a4
to
d6ee031
Compare
d6ee031
to
4f39ffb
Compare
Thanks so much! I'm happy to land this even with the WIP bits. |
Looks like this ended up breaking some links
I don't know why CI didn't catch this... |
Should I submit a new PR to fix them? |
@matthewjasper that'd be great if you have the chance; I just pushed a commit fixing some of them If you have the chance to take the rest, that'd be great! I'd like to get this done today since tomorrow is the cutoff for beta; rust-lang/rust#42353 is the actual PR. |
So this is a WIP attempt to improve the expressions section. It documents more features, fixes inaccuracies and hopefully makes things clearer. All feedback is welcome.
Changes
UFCS (or whatever it's called now) isn't in the reference!!!It has a PR now.Fn
traitsmove
is part of the lambda expression according to libsyntax, so I'm going with thatmove
can extend the lifetime of the closurestatic
s aren't constant expressionsCopy
requirementusize
std::ops::Neg
Deref
worksstd::ops::Not
&mut
can't be applied to everythingwhile
loops()
(Exceptloop
but that's in another PR)if let
semantically equivalence toif
is wrong w.r.t. scope #47 in this respect)if let
andwhile let
clearerUpdate:
libcore
, in only one place.static mut
require unsafe in this chapter.::
in path expressions section.I'll probably split this up into pieces that can more easily be reviewed and avoid blocking everything on the lang team explaining how lvalues actually work.