about summary refs log tree commit diff
path: root/src/libcore
AgeCommit message (Collapse)AuthorLines
2020-05-27Rollup merge of #72626 - phimuemue:doubleendediter_doc, r=dtolnayDylan DPC-0/+26
Add remark regarding DoubleEndedIterator While reviewing https://github.com/rust-itertools/itertools/pull/442/commits/14293bd18f01b6bd4856816222f808f46603eccd#diff-2c16d2ada06ad2fd1fc754679646d471, I realized that a `DoubleEndedIterator` may yield different elements depending on whether it is traversed forwards or backwards. (Not only the *order*, but possibly also the yielded values.) I found this remarkable, but could not find anything in the current docs, so I thought it may be worth mentioning this explicitly. Unfortunately, I could not test these changes locally (`rustdoc` complains about `unresolved import`). Sorry if this causes headache. If I should change something, please let me know. If it seems too trivial, feel free to just close this PR.
2020-05-27Rollup merge of #72606 - GuillaumeGomez:cell-example-update, r=Dylan-DPCDylan DPC-3/+3
Small cell example update r? @Dylan-DPC
2020-05-26Add remark regarding DoubleEndedIteratorphilipp-0/+26
2020-05-26Small cell example updateGuillaume Gomez-3/+3
2020-05-25Rollup merge of #72450 - csmoe:issue-72442, r=oli-obkDylan DPC-0/+1
Fix ice-#72442 Closes #72442 Closes #72426 r? @oli-obk
2020-05-25Rollup merge of #72551 - alilleybrinker:document-debug-stability, r=KodrAusRalf Jung-0/+7
First draft documenting Debug stability. Debug implementations of std types aren't stable, and neither are derived Debug implementations for any types, including user-defined types. This commit adds a section to the Debug documentation noting this stability status. This issue is tracked by #62794.
2020-05-25Rollup merge of #71940 - SimonSapin:nonnull-slice, r=kennytmRalf Jung-0/+61
Add `len` and `slice_from_raw_parts` to `NonNull<[T]>` This follows the precedent of the recently-added `<*const [T]>::len` (adding to its tracking issue https://github.com/rust-lang/rust/issues/71146) and `ptr::slice_from_raw_parts`.
2020-05-24First draft documenting Debug stability.Andrew Lilley Brinker-0/+7
Debug implementations of std types aren't stable, and neither are derived Debug implementations for any types, including user-defined types. This commit adds a section to the Debug documentatio noting this stability status.
2020-05-24Rollup merge of #72535 - saschanaz:patch-1, r=jonas-schievinkRalf Jung-1/+1
Use sort_unstable_by in its own docs Currently it uses `sort_by` instead of itself.
2020-05-24Use sort_unstable_by in its own docsKagami Sascha Rosylight-1/+1
2020-05-24Use `dyn` trait syntax in more comments and docsratijas-4/+4
Probably missed it out during earlier `dyn` refactoring.
2020-05-23Rollup merge of #72431 - RalfJung:ub-warning, r=shepmasterDylan DPC-13/+13
add warning sign to UB examples Just to make it less likely that people miss the fact that these are examples for how to *not* do it.
2020-05-23add warning sign to UB examplesRalf Jung-13/+13
2020-05-22Rollup merge of #72459 - yoshuawuyts:into-future, r=nikomatsakisDylan DPC-0/+31
Add core::future::IntoFuture This patch reintroduces the `core::future::IntoFuture` trait. However unlike earlier PRs this patch does not integrate it into the `async/.await` lowering since that lead to performance regressions. By introducing the trait separately from the integration, the integration PR can be more narrowly scoped, and people can start trying out the `IntoFuture` trait today. Thanks heaps! cc/ @rust-lang/wg-async-foundations ## References - Original PR adding `IntoFuture` https://github.com/rust-lang/rust/pull/65244 - Open issue to re-land `IntoFuture` (assigned to me) https://github.com/rust-lang/rust/issues/67982 - Tracking issue for `IntoFuture` https://github.com/rust-lang/rust/issues/67644
2020-05-22Add core::future::IntoFutureYoshua Wuyts-0/+31
This patch adds `core::future::IntoFuture`. However unlike earlier PRs this patch does not integrate it into the `async/.await` lowering. That integration should be done in a follow-up PR.
2020-05-22Rollup merge of #71607 - RalfJung:pin-drop-panic, r=nikomatsakisRalf Jung-2/+4
clarify interaction of pin drop guarantee and panics Cc https://github.com/rust-lang/unsafe-code-guidelines/issues/232 @Diggsey would this have helped?
2020-05-22only try to suggest for try trait_refcsmoe-0/+1
2020-05-21TypoRalf Jung-1/+1
2020-05-21Improve documentation of `slice::from_raw_parts`Daniel Henry-Mantilla-1/+30
This is to provide a more explicit statement against a code pattern that many people end up coming with, since the reason of it being unsound comes from the badly known single-allocation validity rule. Providing that very pattern as a counter-example could help mitigate that. Co-authored-by: Ralf Jung <post@ralfj.de>
2020-05-21Rollup merge of #72371 - Elrendio:char_documentation, r=steveklabnikRalf Jung-2/+4
FIX - Char documentation for unexperienced users This is my first PR on rust and even if I've read [CONTRIBUTING.md](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#pull-requests) I'm ensure everything is perfect. Sorry if I didn't follow the exact procedure. **What it does:** - Add an example in the char documentation **Explanation** Unexperienced users might not know that punctuation is `Case_Ignorable` and not `Uppercase` and `Lowercase` which mean that when checking if a string is uppercase one might be tempted to write: ```rust my_string.chars().all(char::is_uppercase) ``` However this will return false for `"HELLO WORLD"` which is not intuitive. Since the function `is_case_ignorable` doesn't exists I believe the correct way to check is: ```rust !my_string.chars().any(char::is_lowercase) ``` The aim of this example is to prevent unexperienced users to make an error which punctuation chars.
2020-05-21Rollup merge of #71854 - eduardosm:assoc-char-funcs-and-consts, r=AmanieuRalf Jung-2/+239
Make `std::char` functions and constants associated to `char`. First step to fix https://github.com/rust-lang/rust/issues/71763.
2020-05-21Auto merge of #70705 - lcnr:generic_discriminant, r=nikomatsakisbors-3/+41
Use `T`'s discriminant type in `mem::Discriminant<T>` instead of `u64`. fixes #70509 Adds the lang-item `discriminant_kind`. Updates the function signature of `intrinsics::discriminant_value`. Adds the *probably permanently unstable* trait `DiscriminantKind`. `mem::Discriminant` should now be smaller in some cases. r? @ghost
2020-05-20Rollup merge of #72361 - golddranks:split_inclusive_add_tracking_issue, ↵Dylan DPC-20/+20
r=shepmaster split_inclusive: add tracking issue number (72360) Adds tracking issue number ( https://github.com/rust-lang/rust/issues/72360 ) to the unstable feature attributes.
2020-05-20Rollup merge of #72139 - nnethercote:standalone-fold, r=cuviperDylan DPC-20/+199
Make `fold` standalone. `fold` is currently implemented via `try_fold`, but implementing it directly results in slightly less LLVM IR being generated, speeding up compilation of some benchmarks. r? @cuviper
2020-05-20FIX - Char documentation for unexperienced usersElrendio-2/+4
2020-05-20split_inclusive: add tracking issue number (72360)Pyry Kontio-20/+20
2020-05-19Auto merge of #69171 - Amanieu:new-asm, r=nagisa,nikomatsakisbors-16/+7
Implement new asm! syntax from RFC 2850 This PR implements the new `asm!` syntax proposed in https://github.com/rust-lang/rfcs/pull/2850. # Design A large part of this PR revolves around taking an `asm!` macro invocation and plumbing it through all of the compiler layers down to LLVM codegen. Throughout the various stages, an `InlineAsm` generally consists of 3 components: - The template string, which is stored as an array of `InlineAsmTemplatePiece`. Each piece represents either a literal or a placeholder for an operand (just like format strings). ```rust pub enum InlineAsmTemplatePiece { String(String), Placeholder { operand_idx: usize, modifier: Option<char>, span: Span }, } ``` - The list of operands to the `asm!` (`in`, `[late]out`, `in[late]out`, `sym`, `const`). These are represented differently at each stage of lowering, but follow a common pattern: - `in`, `out` and `inout` all have an associated register class (`reg`) or explicit register (`"eax"`). - `inout` has 2 forms: one with a single expression that is both read from and written to, and one with two separate expressions for the input and output parts. - `out` and `inout` have a `late` flag (`lateout` / `inlateout`) to indicate that the register allocator is allowed to reuse an input register for this output. - `out` and the split variant of `inout` allow `_` to be specified for an output, which means that the output is discarded. This is used to allocate scratch registers for assembly code. - `sym` is a bit special since it only accepts a path expression, which must point to a `static` or a `fn`. - The options set at the end of the `asm!` macro. The only one that is particularly of interest to rustc is `NORETURN` which makes `asm!` return `!` instead of `()`. ```rust bitflags::bitflags! { pub struct InlineAsmOptions: u8 { const PURE = 1 << 0; const NOMEM = 1 << 1; const READONLY = 1 << 2; const PRESERVES_FLAGS = 1 << 3; const NORETURN = 1 << 4; const NOSTACK = 1 << 5; } } ``` ## AST `InlineAsm` is represented as an expression in the AST: ```rust pub struct InlineAsm { pub template: Vec<InlineAsmTemplatePiece>, pub operands: Vec<(InlineAsmOperand, Span)>, pub options: InlineAsmOptions, } pub enum InlineAsmRegOrRegClass { Reg(Symbol), RegClass(Symbol), } pub enum InlineAsmOperand { In { reg: InlineAsmRegOrRegClass, expr: P<Expr>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<P<Expr>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: P<Expr>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: P<Expr>, out_expr: Option<P<Expr>>, }, Const { expr: P<Expr>, }, Sym { expr: P<Expr>, }, } ``` The `asm!` macro is implemented in librustc_builtin_macros and outputs an `InlineAsm` AST node. The template string is parsed using libfmt_macros, positional and named operands are resolved to explicit operand indicies. Since target information is not available to macro invocations, validation of the registers and register classes is deferred to AST lowering. ## HIR `InlineAsm` is represented as an expression in the HIR: ```rust pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], pub operands: &'hir [InlineAsmOperand<'hir>], pub options: InlineAsmOptions, } pub enum InlineAsmRegOrRegClass { Reg(InlineAsmReg), RegClass(InlineAsmRegClass), } pub enum InlineAsmOperand<'hir> { In { reg: InlineAsmRegOrRegClass, expr: Expr<'hir>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<Expr<'hir>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: Expr<'hir>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: Expr<'hir>, out_expr: Option<Expr<'hir>>, }, Const { expr: Expr<'hir>, }, Sym { expr: Expr<'hir>, }, } ``` AST lowering is where `InlineAsmRegOrRegClass` is converted from `Symbol`s to an actual register or register class. If any modifiers are specified for a template string placeholder, these are validated against the set allowed for that operand type. Finally, explicit registers for inputs and outputs are checked for conflicts (same register used for different operands). ## Type checking Each register class has a whitelist of types that it may be used with. After the types of all operands have been determined, the `intrinsicck` pass will check that these types are in the whitelist. It also checks that split `inout` operands have compatible types and that `const` operands are integers or floats. Suggestions are emitted where needed if a template modifier should be used for an operand based on the type that was passed into it. ## HAIR `InlineAsm` is represented as an expression in the HAIR: ```rust crate enum ExprKind<'tcx> { // [..] InlineAsm { template: &'tcx [InlineAsmTemplatePiece], operands: Vec<InlineAsmOperand<'tcx>>, options: InlineAsmOptions, }, } crate enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, expr: ExprRef<'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<ExprRef<'tcx>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: ExprRef<'tcx>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: ExprRef<'tcx>, out_expr: Option<ExprRef<'tcx>>, }, Const { expr: ExprRef<'tcx>, }, SymFn { expr: ExprRef<'tcx>, }, SymStatic { expr: ExprRef<'tcx>, }, } ``` The only significant change compared to HIR is that `Sym` has been lowered to either a `SymFn` whose `expr` is a `Literal` ZST of the `fn`, or a `SymStatic` whose `expr` is a `StaticRef`. ## MIR `InlineAsm` is represented as a `Terminator` in the MIR: ```rust pub enum TerminatorKind<'tcx> { // [..] /// Block ends with an inline assembly block. This is a terminator since /// inline assembly is allowed to diverge. InlineAsm { /// The template for the inline assembly, with placeholders. template: &'tcx [InlineAsmTemplatePiece], /// The operands for the inline assembly, as `Operand`s or `Place`s. operands: Vec<InlineAsmOperand<'tcx>>, /// Miscellaneous options for the inline assembly. options: InlineAsmOptions, /// Destination block after the inline assembly returns, unless it is /// diverging (InlineAsmOptions::NORETURN). destination: Option<BasicBlock>, }, } pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, value: Operand<'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, place: Option<Place<'tcx>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, in_value: Operand<'tcx>, out_place: Option<Place<'tcx>>, }, Const { value: Operand<'tcx>, }, SymFn { value: Box<Constant<'tcx>>, }, SymStatic { value: Box<Constant<'tcx>>, }, } ``` As part of HAIR lowering, `InOut` and `SplitInOut` operands are lowered to a split form with a separate `in_value` and `out_place`. Semantically, the `InlineAsm` terminator is similar to the `Call` terminator except that it has multiple output places where a `Call` only has a single return place output. The constant promotion pass is used to ensure that `const` operands are actually constants (using the same logic as `#[rustc_args_required_const]`). ## Codegen Operands are lowered one more time before being passed to LLVM codegen: ```rust pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { In { reg: InlineAsmRegOrRegClass, value: OperandRef<'tcx, B::Value>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, place: Option<PlaceRef<'tcx, B::Value>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, in_value: OperandRef<'tcx, B::Value>, out_place: Option<PlaceRef<'tcx, B::Value>>, }, Const { string: String, }, SymFn { instance: Instance<'tcx>, }, SymStatic { def_id: DefId, }, } ``` The operands are lowered to LLVM operands and constraint codes as follow: - `out` and the output part of `inout` operands are added first, as required by LLVM. Late output operands have a `=` prefix added to their constraint code, non-late output operands have a `=&` prefix added to their constraint code. - `in` operands are added normally. - `inout` operands are tied to the matching output operand. - `sym` operands are passed as function pointers or pointers, using the `"s"` constraint. - `const` operands are formatted to a string and directly inserted in the template string. The template string is converted to LLVM form: - `$` characters are escaped as `$$`. - `const` operands are converted to strings and inserted directly. - Placeholders are formatted as `${X:M}` where `X` is the operand index and `M` is the modifier character. Modifiers are converted from the Rust form to the LLVM form. The various options are converted to clobber constraints or LLVM attributes, refer to the [RFC](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md#mapping-to-llvm-ir) for more details. Note that LLVM is sometimes rather picky about what types it accepts for certain constraint codes so we sometimes need to insert conversions to/from a supported type. See the target-specific ISelLowering.cpp files in LLVM for details. # Adding support for new architectures Adding inline assembly support to an architecture is mostly a matter of defining the registers and register classes for that architecture. All the definitions for register classes are located in `src/librustc_target/asm/`. Additionally you will need to implement lowering of these register classes to LLVM constraint codes in `src/librustc_codegen_llvm/asm.rs`.
2020-05-19Rollup merge of #72344 - kornelski:assertdoc, r=Mark-SimulacrumDylan DPC-1/+1
Assert doc wording The current wording implies unsafe code is dependent on assert: https://users.rust-lang.org/t/are-assert-statements-included-in-unsafe-blocks/42865
2020-05-19Rollup merge of #71886 - t-rapp:tr-saturating-funcs, r=dtolnayDylan DPC-7/+4
Stabilize saturating_abs and saturating_neg Stabilizes the following signed integer functions with saturation mechanics: * saturating_abs() * saturating_neg() Closes #59983
2020-05-19Assert doc wordingKornel-1/+1
2020-05-19update libcore, add `discriminant_kind` lang-itemBastian Kauschke-3/+41
2020-05-18Apply suggestions from code reviewSimon Sapin-4/+4
Co-authored-by: kennytm <kennytm@gmail.com>
2020-05-18Add `len` and `slice_from_raw_parts` to `NonNull<[T]>`Simon Sapin-0/+61
This follows the precedent of the recently-added `<*const [T]>::len` (adding to its tracking issue https://github.com/rust-lang/rust/issues/71146) and `ptr::slice_from_raw_parts`.
2020-05-18Add documentation for asm!Amanieu d'Antras-8/+7
2020-05-18Un-deprecate asm! macroAmanieu d'Antras-8/+0
2020-05-18Add some more `rfold` implementations.Nicholas Nethercote-0/+68
2020-05-18Rollup merge of #72143 - rust-lang:steveklabnik-must-use, r=sfacklerRalf Jung-0/+14
make offset must_use https://djugei.github.io/bad-at-unsafe/ describes an error a user had when trying to use offset: > At first I just assumed that the .add() and .offset() methods on pointers would mutate the pointer. They do not. Instead they return a new pointer, which gets dropped silently if you don't use it. Unlike for example Result, which is must_use annotated. This PR only adds `offset`, because I wanted to float the idea; I'm imagining that there's more than just `add` and `offset` that could use this. I am also very open to re-wording the warning. r? @rust-lang/libs
2020-05-18Tweak `partition`, `unzip`, `try_find`.Nicholas Nethercote-7/+7
Many default iterator methods use `try_fold` or `fold`, and these ones can too.
2020-05-18Make `fold` standalone.Nicholas Nethercote-13/+124
`fold` is currently implemented via `try_fold`, but implementing it directly results in slightly less LLVM IR being generated, speeding up compilation of some benchmarks. (And likewise for `rfold`.) The commit adds `fold` implementations to all the iterators that lack one but do have a `try_fold` implementation. Most of these just call the `try_fold` implementation directly.
2020-05-17make many ptr functions must_useSteve Klabnik-0/+14
https://djugei.github.io/bad-at-unsafe/ describes an error a user had when trying to use offset: > At first I just assumed that the .add() and .offset() methods on pointers would mutate the pointer. They do not. Instead they return a new pointer, which gets dropped silently if you don't use it. Unlike for example Result, which is must_use annotated.
2020-05-17Auto merge of #72204 - RalfJung:abort, r=Mark-Simulacrumbors-7/+18
make abort intrinsic safe, and correct its documentation Turns out `std::process::abort` is not the same as the intrinsic, the comment was just wrong. Quoting from the unix implementation: ``` // On Unix-like platforms, libc::abort will unregister signal handlers // including the SIGABRT handler, preventing the abort from being blocked, and // fclose streams, with the side effect of flushing them so libc buffered // output will be printed. Additionally the shell will generally print a more // understandable error message like "Abort trap" rather than "Illegal // instruction" that intrinsics::abort would cause, as intrinsics::abort is // implemented as an illegal instruction. ```
2020-05-17make abort intrinsic safe, and correct its documentationRalf Jung-7/+18
2020-05-16emphasize that ManuallyDrop is safe-to-access and unsafe-to-dropRalf Jung-1/+5
2020-05-16Rollup merge of #72166 - nnethercote:simpler-slice-Iterator-methods, r=cuviperDylan DPC-18/+106
Simpler slice `Iterator` methods These reduce the amount of LLVM IR generated, helping compile times. r? @cuviper
2020-05-16Rollup merge of #71625 - Diggsey:improve-manually-drop-docs, r=RalfJungDylan DPC-11/+36
Improve the documentation for ManuallyDrop to resolve conflicting usage of terminology cc @RalfJung Follow-up from https://github.com/rust-lang/unsafe-code-guidelines/issues/233
2020-05-16Rollup merge of #72224 - lzutao:links, r=Dylan-DPCDylan DPC-8/+8
doc: add links to rotate_(left|right)
2020-05-15Improve the documentation for ManuallyDrop to resolve conflicting usage of ↵Diggory Blake-11/+36
terminology.
2020-05-15Auto merge of #69659 - CAD97:step-rework-take-3, r=Amanieubors-198/+608
Rework the std::iter::Step trait Previous attempts: #43127 #62886 #68807 Tracking issue: #42168 This PR reworks the `Step` trait to be phrased in terms of the *successor* and *predecessor* operations. With this, `Step` hopefully has a consistent identity that can have a path towards stabilization. The proposed trait: ```rust /// Objects that have a notion of *successor* and *predecessor* operations. /// /// The *successor* operation moves towards values that compare greater. /// The *predecessor* operation moves towards values that compare lesser. /// /// # Safety /// /// This trait is `unsafe` because its implementation must be correct for /// the safety of `unsafe trait TrustedLen` implementations, and the results /// of using this trait can otherwise be trusted by `unsafe` code to be correct /// and fulful the listed obligations. pub unsafe trait Step: Clone + PartialOrd + Sized { /// Returns the number of *successor* steps required to get from `start` to `end`. /// /// Returns `None` if the number of steps would overflow `usize` /// (or is infinite, or if `end` would never be reached). /// /// # Invariants /// /// For any `a`, `b`, and `n`: /// /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward(&a, n) == Some(b)` /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward(&a, n) == Some(a)` /// * `steps_between(&a, &b) == Some(n)` only if `a <= b` /// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b` /// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`; /// this is the case wheen it would require more than `usize::MAX` steps to get to `b` /// * `steps_between(&a, &b) == None` if `a > b` fn steps_between(start: &Self, end: &Self) -> Option<usize>; /// Returns the value that would be obtained by taking the *successor* /// of `self` `count` times. /// /// If this would overflow the range of values supported by `Self`, returns `None`. /// /// # Invariants /// /// For any `a`, `n`, and `m`: /// /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, m).and_then(|x| Step::forward_checked(x, n))` /// /// For any `a`, `n`, and `m` where `n + m` does not overflow: /// /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, n + m)` /// /// For any `a` and `n`: /// /// * `Step::forward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::forward_checked(&x, 1))` /// * Corollary: `Step::forward_checked(&a, 0) == Some(a)` fn forward_checked(start: Self, count: usize) -> Option<Self>; /// Returns the value that would be obtained by taking the *successor* /// of `self` `count` times. /// /// If this would overflow the range of values supported by `Self`, /// this function is allowed to panic, wrap, or saturate. /// The suggested behavior is to panic when debug assertions are enabled, /// and to wrap or saturate otherwise. /// /// Unsafe code should not rely on the correctness of behavior after overflow. /// /// # Invariants /// /// For any `a`, `n`, and `m`, where no overflow occurs: /// /// * `Step::forward(Step::forward(a, n), m) == Step::forward(a, n + m)` /// /// For any `a` and `n`, where no overflow occurs: /// /// * `Step::forward_checked(a, n) == Some(Step::forward(a, n))` /// * `Step::forward(a, n) == (0..n).fold(a, |x, _| Step::forward(x, 1))` /// * Corollary: `Step::forward(a, 0) == a` /// * `Step::forward(a, n) >= a` /// * `Step::backward(Step::forward(a, n), n) == a` fn forward(start: Self, count: usize) -> Self { Step::forward_checked(start, count).expect("overflow in `Step::forward`") } /// Returns the value that would be obtained by taking the *successor* /// of `self` `count` times. /// /// # Safety /// /// It is undefined behavior for this operation to overflow the /// range of values supported by `Self`. If you cannot guarantee that this /// will not overflow, use `forward` or `forward_checked` instead. /// /// # Invariants /// /// For any `a`: /// /// * if there exists `b` such that `b > a`, it is safe to call `Step::forward_unchecked(a, 1)` /// * if there exists `b`, `n` such that `steps_between(&a, &b) == Some(n)`, /// it is safe to call `Step::forward_unchecked(a, m)` for any `m <= n`. /// /// For any `a` and `n`, where no overflow occurs: /// /// * `Step::forward_unchecked(a, n)` is equivalent to `Step::forward(a, n)` #[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")] unsafe fn forward_unchecked(start: Self, count: usize) -> Self { Step::forward(start, count) } /// Returns the value that would be obtained by taking the *successor* /// of `self` `count` times. /// /// If this would overflow the range of values supported by `Self`, returns `None`. /// /// # Invariants /// /// For any `a`, `n`, and `m`: /// /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == n.checked_add(m).and_then(|x| Step::backward_checked(a, x))` /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == try { Step::backward_checked(a, n.checked_add(m)?) }` /// /// For any `a` and `n`: /// /// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(&x, 1))` /// * Corollary: `Step::backward_checked(&a, 0) == Some(a)` fn backward_checked(start: Self, count: usize) -> Option<Self>; /// Returns the value that would be obtained by taking the *predecessor* /// of `self` `count` times. /// /// If this would overflow the range of values supported by `Self`, /// this function is allowed to panic, wrap, or saturate. /// The suggested behavior is to panic when debug assertions are enabled, /// and to wrap or saturate otherwise. /// /// Unsafe code should not rely on the correctness of behavior after overflow. /// /// # Invariants /// /// For any `a`, `n`, and `m`, where no overflow occurs: /// /// * `Step::backward(Step::backward(a, n), m) == Step::backward(a, n + m)` /// /// For any `a` and `n`, where no overflow occurs: /// /// * `Step::backward_checked(a, n) == Some(Step::backward(a, n))` /// * `Step::backward(a, n) == (0..n).fold(a, |x, _| Step::backward(x, 1))` /// * Corollary: `Step::backward(a, 0) == a` /// * `Step::backward(a, n) <= a` /// * `Step::forward(Step::backward(a, n), n) == a` fn backward(start: Self, count: usize) -> Self { Step::backward_checked(start, count).expect("overflow in `Step::backward`") } /// Returns the value that would be obtained by taking the *predecessor* /// of `self` `count` times. /// /// # Safety /// /// It is undefined behavior for this operation to overflow the /// range of values supported by `Self`. If you cannot guarantee that this /// will not overflow, use `backward` or `backward_checked` instead. /// /// # Invariants /// /// For any `a`: /// /// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)` /// * if there exists `b`, `n` such that `steps_between(&b, &a) == Some(n)`, /// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`. /// /// For any `a` and `n`, where no overflow occurs: /// /// * `Step::backward_unchecked(a, n)` is equivalent to `Step::backward(a, n)` #[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")] unsafe fn backward_unchecked(start: Self, count: usize) -> Self { Step::backward(start, count) } } ``` Note that all of these are associated functions and not callable via method syntax; the calling syntax is always `Step::forward(start, n)`. This version of the trait additionally changes the stepping functions to talk their arguments by value. As opposed to previous attempts which provided a "step by one" method directly, this version of the trait only exposes "step by n". There are a few reasons for this: - `Range*`, the primary consumer of `Step`, assumes that the "step by n" operation is cheap. If a single step function is provided, it will be a lot more enticing to implement "step by n" as n repeated calls to "step by one". While this is not strictly incorrect, this behavior would be surprising for anyone used to using `Range<{primitive integer}>`. - With a trivial default impl, this can be easily added backwards-compatibly later. - The debug-wrapping "step by n" needs to exist for `RangeFrom` to be consistent between "step by n" and "step by one" operation. (Note: the behavior is not changed by this PR, but making the behavior consistent is made tenable by this PR.) Three "kinds" of step are provided: `_checked`, which returns an `Option` indicating attempted overflow; (unsuffixed), which provides "safe overflow" behavior (is allowed to panic, wrap, or saturate, depending on what is most convenient for a given type); and `_unchecked`, which is a version which assumes overflow does not happen. Review is appreciated to check that: - The invariants as described on the `Step` functions are enough to specify the "common sense" consistency for successor/predecessor. - Implementation of `Step` functions is correct in the face of overflow and the edges of representable integers. - Added tests of `Step` functions are asserting the correct behavior (and not just the implemented behavior).
2020-05-15doc: add links to rotate_(left|right)Lzu Tao-8/+8
2020-05-14Auto merge of #71321 - matthewjasper:alloc-min-spec, r=sfacklerbors-0/+9
Use min_specialization in liballoc - Remove a type parameter from `[A]RcFromIter`. - Remove an implementation of `[A]RcFromIter` that didn't actually specialize anything. - Remove unused implementation of `IsZero` for `Option<&mut T>`. - Change specializations of `[A]RcEqIdent` to use a marker trait version of `Eq`. - Remove `BTreeClone`. I couldn't find a way to make this work with `min_specialization`. - Add `rustc_unsafe_specialization_marker` to `Copy` and `TrustedLen`. After this only libcore is the only standard library crate using `feature(specialization)`. cc #31844