-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Document become
keyword
#113095
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
base: master
Are you sure you want to change the base?
Document become
keyword
#113095
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1257,6 +1257,105 @@ mod ref_keyword {} | |||||
/// [`async`]: ../std/keyword.async.html | ||||||
mod return_keyword {} | ||||||
|
||||||
#[doc(keyword = "become")] | ||||||
// | ||||||
/// Perform a tail-call of a function. | ||||||
/// | ||||||
/// <div class="warning"> | ||||||
/// | ||||||
/// `feature(explicit_tail_calls)` is currently incomplete and may not work properly. | ||||||
/// </div> | ||||||
/// | ||||||
/// When tail calling a function, instead of its stack frame being added to the | ||||||
/// stack, the stack frame of the caller is directly replaced with the callee's. | ||||||
/// This means that as long as a loop in a call graph only uses tail calls, the | ||||||
/// stack growth will be bounded. | ||||||
/// | ||||||
/// This is useful for writing functional-style code (since it prevent recursion | ||||||
/// from exhausting resources) or for code optimization (since a tail call | ||||||
/// *might* be cheaper than a normal call, tail calls can be used in a similar | ||||||
/// manner to computed goto). | ||||||
/// | ||||||
/// Example of using `become` to implement functional-style `fold`: | ||||||
/// ``` | ||||||
/// #![feature(explicit_tail_calls)] | ||||||
/// #![expect(incomplete_features)] | ||||||
/// | ||||||
/// fn fold<T: Copy, S>(slice: &[T], init: S, f: impl Fn(S, T) -> S) -> S { | ||||||
/// match slice { | ||||||
/// // without `become`, on big inputs this could easily overflow the | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no actual rule for it, but I will try to explain this: both "big" and "large" are pretty the same in casual speech, but in techical/scientific writings "large" is more preffered term, it just sounds more neutral or formal |
||||||
/// // stack. using a tail call guarantees that the stack will not grow unboundly | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// [first, rest @ ..] => become fold(rest, f(init, *first), f), | ||||||
/// [] => init, | ||||||
/// } | ||||||
/// } | ||||||
/// ``` | ||||||
/// | ||||||
/// Compiler can already perform "tail call optimization" -- it can replace | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I agree with this, can you elaborate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "compiler" is singular and countable, I believe such nouns require a determiner but if we drop the formalities, I just feel that way and sentence does looks more complete with "the" |
||||||
/// normal calls with tail calls (although no guarantees if it will perform it). | ||||||
/// However, to perform TCO, the call needs to be the last thing that happens | ||||||
/// in the functions and be returned from it. This requirement is often broken | ||||||
/// by drop code for locals, which is run after computing the return expression: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is run seems fine to me? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, looking at this now, this is fine as it is |
||||||
/// | ||||||
/// ``` | ||||||
/// fn example() { | ||||||
/// let string = "meow".to_owned(); | ||||||
/// println!("{string}"); | ||||||
/// return help(); // this is *not* the last thing that happens in `example`... | ||||||
/// } | ||||||
/// | ||||||
/// // ... because it is desugared to this: | ||||||
/// fn example_desugared() { | ||||||
/// let string = "meow".to_owned(); | ||||||
/// println!("{string}"); | ||||||
/// let tmp = help(); | ||||||
/// drop(string); | ||||||
/// return tmp; | ||||||
/// } | ||||||
/// | ||||||
/// fn help() {} | ||||||
/// ``` | ||||||
/// | ||||||
/// For this reason `become` also changes the drop order, such that locals are | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// dropped *before* evaluating the call. | ||||||
/// | ||||||
/// In order to guarantee that the compiler can perform a tail call, `become` | ||||||
/// currently has these requirements: | ||||||
/// 1. callee and caller must have the same ABI, arguments and return type | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I believe it is Serial comma case here |
||||||
/// 2. callee and caller must not have varargs | ||||||
/// 3. callee and caller must not be marked with `#[track_caller]` | ||||||
/// 4. callee and caller cannot be a closure | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Shouldn’t it be plural, since |
||||||
/// (unless it's coerced to a function pointer) | ||||||
/// | ||||||
/// It is possible to tail-call a function pointer: | ||||||
/// ``` | ||||||
/// #![feature(explicit_tail_calls)] | ||||||
/// #![expect(incomplete_features)] | ||||||
/// | ||||||
/// #[derive(Copy, Clone)] | ||||||
/// enum Inst { Inc, Dec } | ||||||
/// | ||||||
/// fn dispatch(stream: &[Inst], state: u32) -> u32 { | ||||||
/// const TABLE: &[fn(&[Inst], u32) -> u32] = &[increment, decrement]; | ||||||
/// match stream { | ||||||
/// [inst, rest @ ..] => become TABLE[*inst as usize](rest, state), | ||||||
/// [] => state, | ||||||
/// } | ||||||
/// } | ||||||
/// | ||||||
/// fn increment(stream: &[Inst], state: u32) -> u32 { | ||||||
/// become dispatch(stream, state + 1) | ||||||
/// } | ||||||
/// | ||||||
/// fn decrement(stream: &[Inst], state: u32) -> u32 { | ||||||
/// become dispatch(stream, state - 1) | ||||||
/// } | ||||||
/// | ||||||
/// let program = &[Inst::Inc, Inst::Inc, Inst::Dec, Inst::Inc]; | ||||||
/// assert_eq!(dispatch(program, 0), 2); | ||||||
/// ``` | ||||||
mod become_keyword {} | ||||||
|
||||||
#[doc(keyword = "self")] | ||||||
// | ||||||
/// The receiver of a method, or the current module. | ||||||
|
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.