trans: When coercing to `Box<Trait>` or `Box<[T]>`, leave datum in it's original L-/R-value state.
This fixes a subtle issue where temporaries were being allocated (but not necessarily initialized) to the (parent) terminating scope of a match expression; in particular, the code to zero out the temporary emitted by `datum.store_to` is only attached to the particular match-arm for that temporary, but when going down other arms of the match expression, the temporary may falsely appear to have been initialized, depending on what the stack held at that location, and thus may have its destructor erroneously run at the end of the terminating scope.
FIx#20055.
(There may be a latent bug still remaining in `fn into_fat_ptr`, but I am so annoyed by the test/run-pass/coerce_match.rs failures that I want to land this now.)
Note: Do not merge until we get a newer snapshot that includes #21374
There was some type inference fallout (see 4th commit) because type inference with `a..b` is not as good as with `range(a, b)` (see #21672).
r? @alexcrichton
This fixes a subtle issue where temporaries were being allocated (but
not necessarily initialized) to the (parent) terminating scope of a
match expression; in particular, the code to zero out the temporary
emitted by `datum.store_to` is only attached to the particular
match-arm for that temporary, but when going down other arms of the
match expression, the temporary may falsely appear to have been
initialized, depending on what the stack held at that location, and
thus may have its destructor erroneously run at the end of the
terminating scope.
Test cases to appear in a follow-up commit.
Fix#20055
In preparation for upcoming changes to the `Writer` trait (soon to be called
`Write`) this commit renames the current `write` method to `write_all` to match
the semantics of the upcoming `write_all` method. The `write` method will be
repurposed to return a `usize` indicating how much data was written which
differs from the current `write` semantics. In order to head off as much
unintended breakage as possible, the method is being deprecated now in favor of
a new name.
[breaking-change]
Before ca07e256f62f772d14c42f41af46f2aeacc54983, LLVM's AArch64FastISel
had a sign (and zero?) extension bug. Until rustc gets its LLVM past
that commit, the way of workaround is to pass an option to LLVM that
forces the disabling of FastISel (which would normally kick in for -O0).
Fixes#21627
Two minor improvements that have been on my TODO list for a while:
* Clang uses a size of `-1` for arrays of unknown size and we should do that too as it will tell LLVM to omit the size information in debuginfo.
* There was no LLDB test case for handling the optimized enum representation introduced by @luqmana. This PR finally adds one.
Before:
```
error: invalid operand for inline asm constraint 'i' at line 11
```
Note that 11 is not the line the inline assembly appears in.
After:
```
src/arch/x64/multiboot/bootstrap.rs:203:5: 209:9 error: invalid operand for inline asm constraint 'i'
src/arch/x64/multiboot/bootstrap.rs:203 asm! {
src/arch/x64/multiboot/bootstrap.rs:204 [multiboot => %ecx, mod attsyntax]
src/arch/x64/multiboot/bootstrap.rs:205
src/arch/x64/multiboot/bootstrap.rs:206 ljmp {size_of::<Descriptor>() => %i}, $bootstrap.64
src/arch/x64/multiboot/bootstrap.rs:207 }
src/arch/x64/multiboot/bootstrap.rs:208
...
error: aborting due to previous error
```
E.g. `fn foo() { foo() }`, or, more subtlely
impl Foo for Box<Foo+'static> {
fn bar(&self) {
self.bar();
}
}
The compiler will warn and point out the points where recursion occurs,
if it determines that the function cannot return without calling itself.
Closes#17899.
---
This is highly non-perfect, in particular, my wording above is quite precise, and I have some unresolved questions: This currently will warn about
```rust
fn foo() {
if bar { loop {} }
foo()
}
```
even though `foo` may never be called (i.e. our apparent "unconditional" recursion is actually conditional). I don't know if we should handle this case, and ones like it with `panic!()` instead of `loop` (or anything else that "returns" `!`).
However, strictly speaking, it seems to me that changing the above to not warn will require changing
```rust
fn foo() {
while bar {}
foo()
}
```
to also not warn since it could be that the `while` is an infinite loop and doesn't ever hit the `foo`.
I'm inclined to think we let these cases warn since true edge cases like the first one seem rare, and if they do occur they seem like they would usually be typos in the function call. (I could imagine someone accidentally having code like `fn foo() { assert!(bar()); foo() /* meant to be boo() */ }` which won't warn if the `loop` case is "fixed".)
(Part of the reason this is unresolved is wanting feedback, part of the reason is I couldn't devise a strategy that worked in all cases.)
---
The name `unconditional_self_calls` is kinda clunky; and this reconstructs the CFG for each function that is linted which may or may not be very expensive, I don't know.
This allows one to look at an `ExprMethodCall` `foo.bar()` where `bar`
is a method in some trait and (sometimes) extract the `impl` that `bar`
is defined in, e.g.
trait Foo {
fn bar(&self);
}
impl Foo for uint { // <A>
fn bar(&self) {}
}
fn main() {
1u.bar(); // impl_def_id == Some(<A>)
}
This definitely doesn't handle all cases, but is correct when it is
known, meaning it should only be used for certain linting/heuristic
purposes; no safety analysis.
This should fix issue #20797 (but I don't want to close it automatically).
As the actual fix is very small this would be a perfect candidate for a rollup.
File cannot be written, for example, if directory does not exist.
Before this commit:
```
% rustc -o nonexistent/program program.rs
error: could not write output: No such file or directory
```
With this commit:
```
% rustc -o nonexistent/program program.rs
error: could not write output to nonexistent/program.0.o: No such file or directory
```
This is useful when full rust command is not displayed, or when last error is followed by thousands of warnings.
So far, the source location an LLVM instruction was linked to was controlled by
`debuginfo::set_source_location()` and `debuginfo::clear_source_location()`.
This interface mimicked how LLVM's `IRBuilder` handles debug location
assignment. While this interface has some theoretical performance benefits, it
also makes things terribly unstable: One sets some quasi-global state and then
hopes that it is still correct when a given instruction is emitted---an
assumption that has been proven to not hold a bit too often.
This patch requires the debug source location to be passed to the actual
instruction emitting function. This makes source location assignment explicit
and will prevent future changes to `trans` from accidentally breaking things in
the majority of cases.
This patch does not yet implement the new principle for all instruction kinds
but the stepping experience should have improved significantly nonetheless
already.
This commit is an implementation of [RFC 565][rfc] which is a stabilization of
the `std::fmt` module and the implementations of various formatting traits.
Specifically, the following changes were performed:
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0565-show-string-guidelines.md
* The `Show` trait is now deprecated, it was renamed to `Debug`
* The `String` trait is now deprecated, it was renamed to `Display`
* Many `Debug` and `Display` implementations were audited in accordance with the
RFC and audited implementations now have the `#[stable]` attribute
* Integers and floats no longer print a suffix
* Smart pointers no longer print details that they are a smart pointer
* Paths with `Debug` are now quoted and escape characters
* The `unwrap` methods on `Result` now require `Display` instead of `Debug`
* The `Error` trait no longer has a `detail` method and now requires that
`Display` must be implemented. With the loss of `String`, this has moved into
libcore.
* `impl<E: Error> FromError<E> for Box<Error>` now exists
* `derive(Show)` has been renamed to `derive(Debug)`. This is not currently
warned about due to warnings being emitted on stage1+
While backwards compatibility is attempted to be maintained with a blanket
implementation of `Display` for the old `String` trait (and the same for
`Show`/`Debug`) this is still a breaking change due to primitives no longer
implementing `String` as well as modifications such as `unwrap` and the `Error`
trait. Most code is fairly straightforward to update with a rename or tweaks of
method calls.
[breaking-change]
Closes#21436
After PR #19766 added implicit coersions `*mut T -> *const T`, the explicit casts can be removed.
(The number of such casts turned out to be relatively small).
This commit aims to stabilize the `TypeId` abstraction by moving it out of the
`intrinsics` module into the `any` module of the standard library. Specifically,
* `TypeId` is now defined at `std::any::TypeId`
* `TypeId::hash` has been removed in favor of an implementation of `Hash`.
This commit also performs a final pass over the `any` module, confirming the
following:
* `Any::get_type_id` remains unstable as *usage* of the `Any` trait will likely
never require this, and the `Any` trait does not need to be implemented for
any other types. As a result, this implementation detail can remain unstable
until associated statics are implemented.
* `Any::downcast_ref` is now stable
* `Any::downcast_mut` is now stable
* `BoxAny` remains unstable. While a direct impl on `Box<Any>` is allowed today
it does not allow downcasting of trait objects like `Box<Any + Send>` (those
returned from `Thread::join`). This is covered by #18737.
* `BoxAny::downcast` is now stable.
This commit modifies resolve to prevent conflicts with typedef names in the same
method that conflits are prevented with enum names. This is a breaking change
due to the differing semantics in resolve, and any errors generated on behalf of
this change require that a conflicting typedef, module, or structure to be
renamed so they do not conflict.
[breaking-change]
Closes#6936
LLVM gets overwhelmed when presented with a zeroinitializer for a large
type. In unoptimised builds, it generates a long sequence of stores to
memory. In optmised builds, it manages to generate a standard memset of
zero values, but takes a long time doing so.
Call out to the `llvm.memset` function to zero out the memory instead.
Fixes#21264
This commit aims to stabilize the `TypeId` abstraction by moving it out of the
`intrinsics` module into the `any` module of the standard library. Specifically,
* `TypeId` is now defined at `std::any::TypeId`
* `TypeId::hash` has been removed in favor of an implementation of `Hash`.
This commit also performs a final pass over the `any` module, confirming the
following:
* `Any::get_type_id` remains unstable as *usage* of the `Any` trait will likely
never require this, and the `Any` trait does not need to be implemented for
any other types. As a result, this implementation detail can remain unstable
until associated statics are implemented.
* `Any::downcast_ref` is now stable
* `Any::downcast_mut` is now stable
* `BoxAny` remains unstable. While a direct impl on `Box<Any>` is allowed today
it does not allow downcasting of trait objects like `Box<Any + Send>` (those
returned from `Thread::join`). This is covered by #18737.
* `BoxAny::downcast` is now stable.
LLVM gets overwhelmed when presented with a zeroinitializer for a large
type. In unoptimised builds, it generates a long sequence of stores to
memory. In optmised builds, it manages to generate a standard memset of
zero values, but takes a long time doing so.
Call out to the `llvm.memset` function to zero out the memory instead.
File cannot be written, for example, if directory does not exist.
Before this commit:
```
% rustc -o nonexistent/program program.rs
error: could not write output: No such file or directory
```
With this commit:
```
% rustc -o nonexistent/program program.rs
error: could not write output to nonexistent/program.0.o: No such file or directory
```
This is useful when full rust command is not displayed, or when last
error is preceded by thousands of warnings.
This stops the compiler ICEing on the use of SIMD types in FFI signatures. It emits correct code for LLVM intrinsics, but I am quite unsure about the ABI handling in general so I've added a new feature gate `simd_ffi` to try to ensure people don't use it without realising there's a non-trivial risk of codegen brokenness.
Closes#20043.
I don't know if this handling of SIMD types is correct for the C ABI on
all platforms, so lets add an even finer feature gate than just the
`simd` one.
The `simd` one can be used with (relatively) little risk of complete
nonsense, the reason for it is that it is likely that things will
change. Using the types in FFI with an incorrect ABI will at best give
absolute nonsense results, but possibly cause serious breakage too, so
this is a step up in badness, hence a new feature gate.
With the addition of separate search paths to the compiler, it was intended that
applications such as Cargo could require a `--extern` flag per `extern crate`
directive in the source. The system can currently be subverted, however, due to
the `existing_match()` logic in the crate loader.
When loading crates we first attempt to match an `extern crate` directive
against all previously loaded crates to avoid reading metadata twice. This "hit
the cache if possible" step was erroneously leaking crates across the search
path boundaries, however. For example:
extern crate b;
extern crate a;
If `b` depends on `a`, then it will load crate `a` when the `extern crate b`
directive is being processed. When the compiler reaches `extern crate a` it will
use the previously loaded version no matter what. If the compiler was not
invoked with `-L crate=path/to/a`, it will still succeed.
This behavior is allowing `extern crate` declarations in Cargo without a
corresponding declaration in the manifest of a dependency, which is considered
a bug.
This commit fixes this problem by keeping track of the origin search path for a
crate. Crates loaded from the dependency search path are not candidates for
crates which are loaded from the crate search path.
With the addition of separate search paths to the compiler, it was intended that
applications such as Cargo could require a `--extern` flag per `extern crate`
directive in the source. The system can currently be subverted, however, due to
the `existing_match()` logic in the crate loader.
When loading crates we first attempt to match an `extern crate` directive
against all previously loaded crates to avoid reading metadata twice. This "hit
the cache if possible" step was erroneously leaking crates across the search
path boundaries, however. For example:
extern crate b;
extern crate a;
If `b` depends on `a`, then it will load crate `a` when the `extern crate b`
directive is being processed. When the compiler reaches `extern crate a` it will
use the previously loaded version no matter what. If the compiler was not
invoked with `-L crate=path/to/a`, it will still succeed.
This behavior is allowing `extern crate` declarations in Cargo without a
corresponding declaration in the manifest of a dependency, which is considered
a bug.
This commit fixes this problem by keeping track of the origin search path for a
crate. Crates loaded from the dependency search path are not candidates for
crates which are loaded from the crate search path.
As a result of this fix, this is a likely a breaking change for a number of
Cargo packages. If the compiler starts informing that a crate can no longer be
found, it likely means that the dependency was forgotten in your Cargo.toml.
[breaking-change]
This seems to match what clang does on arm, but I cannot do any
experimentation with mips, but it matches how the LLVM intrinsics are
defined in any case...
Unlike the intrinics in C, this types the SSE values base on integer
size. This matches the LLVM intrinsics which have concrete vector types
(`<4 x i32>` etc.), and is no loss of expressivity: if one is using a C
function that really takes an untyped integral SSE value, just give it
whatever Rust type makes most sense.
While it's unstable and will probably be replaced or "reformed" at some point, it's useful in the mean time to be able to introspect the type system when debugging, and not be limited to sized types.
Fixes#21058
There are two places left where we used to only know the byte
size of/offset into an array and had to cast to i8 and back to get the
right addresses. But by now, we always know the sizes in terms of the
number of elements in the array. In fact we have to add an extra Mul
instruction so we can use the weird cast-to-u8 code. So we should really
just embrace our new knowledge and use simple GEPs to do the address
calculations.
Fixes#3729
Originally, this was going to be discussed and revisted, however I've been working on this for months, and a rebase on top of master was about 1 flight's worth of work so I just went ahead and did it.
This gets you as far as being able to target powerpc with, eg:
LD_LIBRARY_PATH=./x86_64-unknown-linux-gnu/stage2/lib/ x86_64-unknown-linux-gnu/stage2/bin/rustc -C linker=powerpc-linux-gnu-gcc --target powerpc-unknown-linux-gnu hello.rs
Would really love to get this out before 1.0. r? @alexcrichton
There are two places left where we used to only know the byte
size of/offset into an array and had to cast to i8 and back to get the
right addresses. But by now, we always know the sizes in terms of the
number of elements in the array. In fact we have to add an extra Mul
instruction so we can use the weird cast-to-u8 code. So we should really
just embrace our new knowledge and use simple GEPs to do the address
calculations.
Additionally, the pointer calculations in bind_subslice_pat don't handle
zero-sized types correctly, producing slices that point outside the
array that is being matched against. Using GEP fixes that as well.
Fixes#3729
Currently, small aggregates are passed to functions as immediate values
as is. This has two consequences.
One is that aggregates are passed component-wise by LLVM, so e.g. a
struct containing four u8 values (e.g. an RGBA struct) will be passed as
four individual values.
The other is that LLVM isn't very good at optimizing loads/stores of
first class attributes. What clang does is converting the aggregate to
an appropriately sized integer type (e.g. i32 for the four u8 values),
and using that for the function argument. This allows LLVM to create
code that is a lot better.
Fixes#20450#20149#16506#13927
Currently even small fixed-size arrays are passed as indirect
parameters, which seems to be just an oversight. Let's handle them the
same as structs of the same size, passing them as immediate values.
Currently, small aggregates are passed to functions as immediate values
as is. This has two consequences.
One is that aggregates are passed component-wise by LLVM, so e.g. a
struct containing four u8 values (e.g. an RGBA struct) will be passed as
four individual values.
The other is that LLVM isn't very good at optimizing loads/stores of
first class attributes. What clang does is converting the aggregate to
an appropriately sized integer type (e.g. i32 for the four u8 values),
and using that for the function argument. This allows LLVM to create
code that is a lot better.
Fixes#20450#20149#16506#13927
Currently we pass a `struct S(u64)` as an immediate value on i686, but a
`struct S { x: u64 }` is passed indirectly. This seems pretty wrong,
as they both have the same underlying LLVM type `{ i64 }`, no sense in
treating them differently.
This gets rid of the 'experimental' level, removes the non-staged_api
case (i.e. stability levels for out-of-tree crates), and lets the
staged_api attributes use 'unstable' and 'deprecated' lints.
This makes the transition period to the full feature staging design
a bit nicer.
This gets rid of the 'experimental' level, removes the non-staged_api
case (i.e. stability levels for out-of-tree crates), and lets the
staged_api attributes use 'unstable' and 'deprecated' lints.
This makes the transition period to the full feature staging design
a bit nicer.
This partially implements the feature staging described in the
[release channel RFC][rc]. It does not yet fully conform to the RFC as
written, but does accomplish its goals sufficiently for the 1.0 alpha
release.
It has three primary user-visible effects:
* On the nightly channel, use of unstable APIs generates a warning.
* On the beta channel, use of unstable APIs generates a warning.
* On the beta channel, use of feature gates generates a warning.
Code that does not trigger these warnings is considered 'stable',
modulo pre-1.0 bugs.
Disabling the warnings for unstable APIs continues to be done in the
existing (i.e. old) style, via `#[allow(...)]`, not that specified in
the RFC. I deem this marginally acceptable since any code that must do
this is not using the stable dialect of Rust.
Use of feature gates is itself gated with the new 'unstable_features'
lint, on nightly set to 'allow', and on beta 'warn'.
The attribute scheme used here corresponds to an older version of the
RFC, with the `#[staged_api]` crate attribute toggling the staging
behavior of the stability attributes, but the user impact is only
in-tree so I'm not concerned about having to make design changes later
(and I may ultimately prefer the scheme here after all, with the
`#[staged_api]` crate attribute).
Since the Rust codebase itself makes use of unstable features the
compiler and build system do a midly elaborate dance to allow it to
bootstrap while disobeying these lints (which would otherwise be
errors because Rust builds with `-D warnings`).
This patch includes one significant hack that causes a
regression. Because the `format_args!` macro emits calls to unstable
APIs it would trigger the lint. I added a hack to the lint to make it
not trigger, but this in turn causes arguments to `println!` not to be
checked for feature gates. I don't presently understand macro
expansion well enough to fix. This is bug #20661.
Closes#16678
[rc]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md
Next steps are to disable the existing out-of-tree behavior for stability attributes, and convert the remaining system to be feature-based per the RFC. During the first beta cycle we will set these lints to 'forbid'.
This commit aims to prepare the `std::hash` module for alpha by formalizing its
current interface whileholding off on adding `#[stable]` to the new APIs. The
current usage with the `HashMap` and `HashSet` types is also reconciled by
separating out composable parts of the design. The primary goal of this slight
redesign is to separate the concepts of a hasher's state from a hashing
algorithm itself.
The primary change of this commit is to separate the `Hasher` trait into a
`Hasher` and a `HashState` trait. Conceptually the old `Hasher` trait was
actually just a factory for various states, but hashing had very little control
over how these states were used. Additionally the old `Hasher` trait was
actually fairly unrelated to hashing.
This commit redesigns the existing `Hasher` trait to match what the notion of a
`Hasher` normally implies with the following definition:
trait Hasher {
type Output;
fn reset(&mut self);
fn finish(&self) -> Output;
}
This `Hasher` trait emphasizes that hashing algorithms may produce outputs other
than a `u64`, so the output type is made generic. Other than that, however, very
little is assumed about a particular hasher. It is left up to implementors to
provide specific methods or trait implementations to feed data into a hasher.
The corresponding `Hash` trait becomes:
trait Hash<H: Hasher> {
fn hash(&self, &mut H);
}
The old default of `SipState` was removed from this trait as it's not something
that we're willing to stabilize until the end of time, but the type parameter is
always required to implement `Hasher`. Note that the type parameter `H` remains
on the trait to enable multidispatch for specialization of hashing for
particular hashers.
Note that `Writer` is not mentioned in either of `Hash` or `Hasher`, it is
simply used as part `derive` and the implementations for all primitive types.
With these definitions, the old `Hasher` trait is realized as a new `HashState`
trait in the `collections::hash_state` module as an unstable addition for
now. The current definition looks like:
trait HashState {
type Hasher: Hasher;
fn hasher(&self) -> Hasher;
}
The purpose of this trait is to emphasize that the one piece of functionality
for implementors is that new instances of `Hasher` can be created. This
conceptually represents the two keys from which more instances of a
`SipHasher` can be created, and a `HashState` is what's stored in a
`HashMap`, not a `Hasher`.
Implementors of custom hash algorithms should implement the `Hasher` trait, and
only hash algorithms intended for use in hash maps need to implement or worry
about the `HashState` trait.
The entire module and `HashState` infrastructure remains `#[unstable]` due to it
being recently redesigned, but some other stability decision made for the
`std::hash` module are:
* The `Writer` trait remains `#[experimental]` as it's intended to be replaced
with an `io::Writer` (more details soon).
* The top-level `hash` function is `#[unstable]` as it is intended to be generic
over the hashing algorithm instead of hardwired to `SipHasher`
* The inner `sip` module is now private as its one export, `SipHasher` is
reexported in the `hash` module.
And finally, a few changes were made to the default parameters on `HashMap`.
* The `RandomSipHasher` default type parameter was renamed to `RandomState`.
This renaming emphasizes that it is not a hasher, but rather just state to
generate hashers. It also moves away from the name "sip" as it may not always
be implemented as `SipHasher`. This type lives in the
`std::collections::hash_map` module as `#[unstable]`
* The associated `Hasher` type of `RandomState` is creatively called...
`Hasher`! This concrete structure lives next to `RandomState` as an
implemenation of the "default hashing algorithm" used for a `HashMap`. Under
the hood this is currently implemented as `SipHasher`, but it draws an
explicit interface for now and allows us to modify the implementation over
time if necessary.
There are many breaking changes outlined above, and as a result this commit is
a:
[breaking-change]
To avoid using the feauture, change uses of `box <expr>` to
`Box::new(<expr>)` alternative, as noted by the feature gate message.
(Note that box patterns have no analogous trivial replacement, at
least not in general; you need to revise the code to do a partial
match, deref, and then the rest of the match.)
[breaking-change]
This partially implements the feature staging described in the
[release channel RFC][rc]. It does not yet fully conform to the RFC as
written, but does accomplish its goals sufficiently for the 1.0 alpha
release.
It has three primary user-visible effects:
* On the nightly channel, use of unstable APIs generates a warning.
* On the beta channel, use of unstable APIs generates a warning.
* On the beta channel, use of feature gates generates a warning.
Code that does not trigger these warnings is considered 'stable',
modulo pre-1.0 bugs.
Disabling the warnings for unstable APIs continues to be done in the
existing (i.e. old) style, via `#[allow(...)]`, not that specified in
the RFC. I deem this marginally acceptable since any code that must do
this is not using the stable dialect of Rust.
Use of feature gates is itself gated with the new 'unstable_features'
lint, on nightly set to 'allow', and on beta 'warn'.
The attribute scheme used here corresponds to an older version of the
RFC, with the `#[staged_api]` crate attribute toggling the staging
behavior of the stability attributes, but the user impact is only
in-tree so I'm not concerned about having to make design changes later
(and I may ultimately prefer the scheme here after all, with the
`#[staged_api]` crate attribute).
Since the Rust codebase itself makes use of unstable features the
compiler and build system to a midly elaborate dance to allow it to
bootstrap while disobeying these lints (which would otherwise be
errors because Rust builds with `-D warnings`).
This patch includes one significant hack that causes a
regression. Because the `format_args!` macro emits calls to unstable
APIs it would trigger the lint. I added a hack to the lint to make it
not trigger, but this in turn causes arguments to `println!` not to be
checked for feature gates. I don't presently understand macro
expansion well enough to fix. This is bug #20661.
Closes#16678
[rc]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md
This commit aims to prepare the `std::hash` module for alpha by formalizing its
current interface whileholding off on adding `#[stable]` to the new APIs. The
current usage with the `HashMap` and `HashSet` types is also reconciled by
separating out composable parts of the design. The primary goal of this slight
redesign is to separate the concepts of a hasher's state from a hashing
algorithm itself.
The primary change of this commit is to separate the `Hasher` trait into a
`Hasher` and a `HashState` trait. Conceptually the old `Hasher` trait was
actually just a factory for various states, but hashing had very little control
over how these states were used. Additionally the old `Hasher` trait was
actually fairly unrelated to hashing.
This commit redesigns the existing `Hasher` trait to match what the notion of a
`Hasher` normally implies with the following definition:
trait Hasher {
type Output;
fn reset(&mut self);
fn finish(&self) -> Output;
}
This `Hasher` trait emphasizes that hashing algorithms may produce outputs other
than a `u64`, so the output type is made generic. Other than that, however, very
little is assumed about a particular hasher. It is left up to implementors to
provide specific methods or trait implementations to feed data into a hasher.
The corresponding `Hash` trait becomes:
trait Hash<H: Hasher> {
fn hash(&self, &mut H);
}
The old default of `SipState` was removed from this trait as it's not something
that we're willing to stabilize until the end of time, but the type parameter is
always required to implement `Hasher`. Note that the type parameter `H` remains
on the trait to enable multidispatch for specialization of hashing for
particular hashers.
Note that `Writer` is not mentioned in either of `Hash` or `Hasher`, it is
simply used as part `derive` and the implementations for all primitive types.
With these definitions, the old `Hasher` trait is realized as a new `HashState`
trait in the `collections::hash_state` module as an unstable addition for
now. The current definition looks like:
trait HashState {
type Hasher: Hasher;
fn hasher(&self) -> Hasher;
}
The purpose of this trait is to emphasize that the one piece of functionality
for implementors is that new instances of `Hasher` can be created. This
conceptually represents the two keys from which more instances of a
`SipHasher` can be created, and a `HashState` is what's stored in a
`HashMap`, not a `Hasher`.
Implementors of custom hash algorithms should implement the `Hasher` trait, and
only hash algorithms intended for use in hash maps need to implement or worry
about the `HashState` trait.
The entire module and `HashState` infrastructure remains `#[unstable]` due to it
being recently redesigned, but some other stability decision made for the
`std::hash` module are:
* The `Writer` trait remains `#[experimental]` as it's intended to be replaced
with an `io::Writer` (more details soon).
* The top-level `hash` function is `#[unstable]` as it is intended to be generic
over the hashing algorithm instead of hardwired to `SipHasher`
* The inner `sip` module is now private as its one export, `SipHasher` is
reexported in the `hash` module.
And finally, a few changes were made to the default parameters on `HashMap`.
* The `RandomSipHasher` default type parameter was renamed to `RandomState`.
This renaming emphasizes that it is not a hasher, but rather just state to
generate hashers. It also moves away from the name "sip" as it may not always
be implemented as `SipHasher`. This type lives in the
`std::collections::hash_map` module as `#[unstable]`
* The associated `Hasher` type of `RandomState` is creatively called...
`Hasher`! This concrete structure lives next to `RandomState` as an
implemenation of the "default hashing algorithm" used for a `HashMap`. Under
the hood this is currently implemented as `SipHasher`, but it draws an
explicit interface for now and allows us to modify the implementation over
time if necessary.
There are many breaking changes outlined above, and as a result this commit is
a:
[breaking-change]
always were but it's dang annoying to weed out all the places that
fail to meet the assertion, and it doesn't really hurt things if we don't
always get it right.
This commit takes a first pass at stabilizing `std::thread`:
* It removes the `detach` method in favor of two constructors -- `spawn`
for detached threads, `scoped` for "scoped" (i.e., must-join)
threads. This addresses some of the surprise/frustrating debug
sessions with the previous API, in which `spawn` produced a guard that
on destruction joined the thread (unless `detach` was called).
The reason to have the division in part is that `Send` will soon not
imply `'static`, which means that `scoped` thread creation can take a
closure over *shared stack data* of the parent thread. On the other
hand, this means that the parent must not pop the relevant stack
frames while the child thread is running. The `JoinGuard` is used to
prevent this from happening by joining on drop (if you have not
already explicitly `join`ed.) The APIs around `scoped` are
future-proofed for the `Send` changes by taking an additional lifetime
parameter. With the current definition of `Send`, this is forced to be
`'static`, but when `Send` changes these APIs will gain their full
flexibility immediately.
Threads that are `spawn`ed, on the other hand, are detached from the
start and do not yield an RAII guard.
The hope is that, by making `scoped` an explicit opt-in with a very
suggestive name, it will be drastically less likely to be caught by a
surprising deadlock due to an implicit join at the end of a scope.
* The module itself is marked stable.
* Existing methods other than `spawn` and `scoped` are marked stable.
The migration path is:
```rust
Thread::spawn(f).detached()
```
becomes
```rust
Thread::spawn(f)
```
while
```rust
let res = Thread::spawn(f);
res.join()
```
becomes
```rust
let res = Thread::scoped(f);
res.join()
```
[breaking-change]
fmt::Show is for debugging, and can and should be implemented for
all public types. This trait is used with `{:?}` syntax. There still
exists #[derive(Show)].
fmt::String is for types that faithfully be represented as a String.
Because of this, there is no way to derive fmt::String, all
implementations must be purposeful. It is used by the default format
syntax, `{}`.
This will break most instances of `{}`, since that now requires the type
to impl fmt::String. In most cases, replacing `{}` with `{:?}` is the
correct fix. Types that were being printed specifically for users should
receive a fmt::String implementation to fix this.
Part of #20013
[breaking-change]
This commit is an implementation of [RFC 494][rfc] which removes the entire
`std::c_vec` module and redesigns the `std::c_str` module as `std::ffi`.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0494-c_str-and-c_vec-stability.md
The interface of the new `CString` is outlined in the linked RFC, the primary
changes being:
* The `ToCStr` trait is gone, meaning the `with_c_str` and `to_c_str` methods
are now gone. These two methods are replaced with a `CString::from_slice`
method.
* The `CString` type is now just a wrapper around `Vec<u8>` with a static
guarantee that there is a trailing nul byte with no internal nul bytes. This
means that `CString` now implements `Deref<Target = [c_char]>`, which is where
it gains most of its methods from. A few helper methods are added to acquire a
slice of `u8` instead of `c_char`, as well as including a slice with the
trailing nul byte if necessary.
* All usage of non-owned `CString` values is now done via two functions inside
of `std::ffi`, called `c_str_to_bytes` and `c_str_to_bytes_with_nul`. These
functions are now the one method used to convert a `*const c_char` to a Rust
slice of `u8`.
Many more details, including newly deprecated methods, can be found linked in
the RFC. This is a:
[breaking-change]
Closes#20444
macro_rules! is like an item that defines a macro. Other items don't have a
trailing semicolon, or use a paren-delimited body.
If there's an argument for matching the invocation syntax, e.g. parentheses for
an expr macro, then I think that applies more strongly to the *inner*
delimiters on the LHS, wrapping the individual argument patterns.
This commit is an implementation of [RFC 494][rfc] which removes the entire
`std::c_vec` module and redesigns the `std::c_str` module as `std::ffi`.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0494-c_str-and-c_vec-stability.md
The interface of the new `CString` is outlined in the linked RFC, the primary
changes being:
* The `ToCStr` trait is gone, meaning the `with_c_str` and `to_c_str` methods
are now gone. These two methods are replaced with a `CString::from_slice`
method.
* The `CString` type is now just a wrapper around `Vec<u8>` with a static
guarantee that there is a trailing nul byte with no internal nul bytes. This
means that `CString` now implements `Deref<Target = [c_char]>`, which is where
it gains most of its methods from. A few helper methods are added to acquire a
slice of `u8` instead of `c_char`, as well as including a slice with the
trailing nul byte if necessary.
* All usage of non-owned `CString` values is now done via two functions inside
of `std::ffi`, called `c_str_to_bytes` and `c_str_to_bytes_with_nul`. These
functions are now the one method used to convert a `*const c_char` to a Rust
slice of `u8`.
Many more details, including newly deprecated methods, can be found linked in
the RFC. This is a:
[breaking-change]
Closes#20444
This implements RFC 179 by making the pattern `&<pat>` require matching
against a variable of type `&T`, and introducing the pattern `&mut
<pat>` which only works with variables of type `&mut T`.
The pattern `&mut x` currently parses as `&(mut x)` i.e. a pattern match
through a `&T` or a `&mut T` that binds the variable `x` to have type
`T` and to be mutable. This should be rewritten as follows, for example,
for &mut x in slice.iter() {
becomes
for &x in slice.iter() {
let mut x = x;
Due to this, this is a
[breaking-change]
Closes#20496.
This commit introduces the syntax for negative implementations of traits
as shown below:
`impl !Trait for Type {}`
cc #13231
Part of RFC rust-lang/rfcs#127
r? @nikomatsakis
Use autoderef for call notation. This is consistent in that we now autoderef all postfix operators (`.`, `[]`, and `()`). It also means you can call closures without writing `(*f)()`. Note that this is rebased atop the rollup, so only the final commit is relevant.
r? @pcwalton
closes#20486closes#20474closes#20441
[breaking-change]
The `Index[Mut]` traits now have one less input parameter, as the return type of the indexing operation is an associated type. This breaks all existing implementations.
---
binop traits (`Add`, `Sub`, etc) now have an associated type for their return type. Also, the RHS input parameter now defaults to `Self` (except for the `Shl` and `Shr` traits). For example, the `Add` trait now looks like this:
``` rust
trait Add<Rhs=Self> {
type Output;
fn add(self, Rhs) -> Self::Output;
}
```
The `Neg` and `Not` traits now also have an associated type for their return type.
This breaks all existing implementations of these traits.
---
Affected traits:
- `Iterator { type Item }`
- `IteratorExt` no input/output types, uses `<Self as Iterator>::Item` in its methods
- `DoubleEndedIterator` no input/output types, uses `<Self as Iterator>::Item` in its methods
- `DoubleEndedIteratorExt` no input/output types, uses `<Self as Iterator>::Item` in its methods
- `RandomAccessIterator` no input/output types
- `ExactSizeIterator` no input/output types, uses `<Self as Iterator>::Item` in its methods
This breaks all the implementations of these traits.
`UnboxedClosureTyper`. This requires adding a `tcx` field to
`ParameterEnvironment` but generally simplifies everything since we
only need to pass along an `UnboxedClosureTyper` or `Typer`.
which should always result in an error.
NB. Some of the hunks in this commit rely on a later commit which adds
`tcx` into `param_env` and modifies `ParameterEnvironment` to
implement `Typer`.
This corresponds to the JMM memory model's non-volatile reads and writes to shared variables. It provides fairly weak guarantees, but prevents UB (specifically, you will never see a value that was not written _at some point_ to the provided location). It is not part of the C++ memory model and is only legal to provide to LLVM for loads and stores (not fences, atomicrmw, etc.).
Valid uses of this ordering are things like racy counters where you don't care about the operation actually being atomic, just want to avoid UB. It cannot be used for synchronization without additional memory barriers since unordered loads and stores may be reordered freely by the optimizer (this is the main way it differs from relaxed).
Because it is new to Rust and it provides so few guarantees, for now only the intrinsic is provided--this patch doesn't add it to any of the higher-level atomic wrappers.
This commit is an implementation of [RFC 503][rfc] which is a stabilization
story for the prelude. Most of the RFC was directly applied, removing reexports.
Some reexports are kept around, however:
* `range` remains until range syntax has landed to reduce churn.
* `Path` and `GenericPath` remain until path reform lands. This is done to
prevent many imports of `GenericPath` which will soon be removed.
* All `io` traits remain until I/O reform lands so imports can be rewritten all
at once to `std::io::prelude::*`.
This is a breaking change because many prelude reexports have been removed, and
the RFC can be consulted for the exact list of removed reexports, as well as to
find the locations of where to import them.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0503-prelude-stabilization.md
[breaking-change]
Closes#20068
This is a [breaking-change]. The new rules require that, for an impl of a trait defined
in some other crate, two conditions must hold:
1. Some type must be local.
2. Every type parameter must appear "under" some local type.
Here are some examples that are legal:
```rust
struct MyStruct<T> { ... }
// Here `T` appears "under' `MyStruct`.
impl<T> Clone for MyStruct<T> { }
// Here `T` appears "under' `MyStruct` as well. Note that it also appears
// elsewhere.
impl<T> Iterator<T> for MyStruct<T> { }
```
Here is an illegal example:
```rust
// Here `U` does not appear "under" `MyStruct` or any other local type.
// We call `U` "uncovered".
impl<T,U> Iterator<U> for MyStruct<T> { }
```
There are a couple of ways to rewrite this last example so that it is
legal:
1. In some cases, the uncovered type parameter (here, `U`) should be converted
into an associated type. This is however a non-local change that requires access
to the original trait. Also, associated types are not fully baked.
2. Add `U` as a type parameter of `MyStruct`:
```rust
struct MyStruct<T,U> { ... }
impl<T,U> Iterator<U> for MyStruct<T,U> { }
```
3. Create a newtype wrapper for `U`
```rust
impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { }
```
Because associated types are not fully baked, which in the case of the
`Hash` trait makes adhering to this rule impossible, you can
temporarily disable this rule in your crate by using
`#![feature(old_orphan_check)]`. Note that the `old_orphan_check`
feature will be removed before 1.0 is released.
These changes fix various problems encountered getting japaric's `at-iter` branch to work. This branch converts the `Iterator` trait to use an associated type.
This pass performs a second pass of stabilization through the `std::sync`
module, avoiding modules/types that are being handled in other PRs (e.g.
mutexes, rwlocks, condvars, and channels).
The following items are now stable
* `sync::atomic`
* `sync::atomic::ATOMIC_BOOL_INIT` (was `INIT_ATOMIC_BOOL`)
* `sync::atomic::ATOMIC_INT_INIT` (was `INIT_ATOMIC_INT`)
* `sync::atomic::ATOMIC_UINT_INIT` (was `INIT_ATOMIC_UINT`)
* `sync::Once`
* `sync::ONCE_INIT`
* `sync::Once::call_once` (was `doit`)
* C == `pthread_once(..)`
* Boost == `call_once(..)`
* Windows == `InitOnceExecuteOnce`
* `sync::Barrier`
* `sync::Barrier::new`
* `sync::Barrier::wait` (now returns a `bool`)
* `sync::Semaphore::new`
* `sync::Semaphore::acquire`
* `sync::Semaphore::release`
The following items remain unstable
* `sync::SemaphoreGuard`
* `sync::Semaphore::access` - it's unclear how this relates to the poisoning
story of mutexes.
* `sync::TaskPool` - the semantics of a failing task and whether a thread is
re-attached to a thread pool are somewhat unclear, and the
utility of this type in `sync` is question with respect to
the jobs of other primitives. This type will likely become
stable or move out of the standard library over time.
* `sync::Future` - futures as-is have yet to be deeply re-evaluated with the
recent core changes to Rust's synchronization story, and will
likely become stable in the future but are unstable until
that time comes.
[breaking-change]
The the last argument of the `ItemDecorator::expand` method has changed to `Box<FnMut>`. Syntax extensions will break.
[breaking-change]
---
This PR removes pretty much all the remaining uses of boxed closures from the libraries. There are still boxed closures under the `test` directory, but I think those should be removed or replaced with unboxed closures at the same time we remove boxed closures from the language.
In a few places I had to do some contortions (see the first commit for an example) to work around issue #19596. I have marked those workarounds with FIXMEs. In the future when `&mut F where F: FnMut` implements the `FnMut` trait, we should be able to remove those workarounds. I've take care to avoid placing the workaround functions in the public API.
Since `let f = || {}` always gets type checked as a boxed closure, I have explictly annotated those closures (with e.g. `|&:| {}`) to force the compiler to type check them as unboxed closures.
Instead of removing the type aliases (like `GetCrateDataCb`), I could have replaced them with newtypes. But this seemed like overcomplicating things for little to no gain.
I think we should be able to remove the boxed closures from the languge after this PR lands. (I'm being optimistic here)
r? @alexcrichton or @aturon
cc @nikomatsakis
This pull request adds the `rust-gdb` shell script which starts GDB with Rust pretty printers enabled. The PR also makes `rustc` add a special `.debug_gdb_scripts` ELF section on Linux which tells GDB that the produced binary should use the Rust pretty printers.
Note that at the moment this script will only work and be installed on Linux. On Mac OS X there's `rust-lldb` which works much better there. On Windows I had too many problems making this stable. I'll give it another try soonish.
You can use this script just like you would use GDB from the command line. It will use the pretty printers from the Rust "installation" found first in PATH. E.g. if you have `~/rust/x86_64-linux-gnu/stage1/bin` in your path, it will use the pretty printer scripts in `~/rust/x86_64-linux-gnu/stage1/lib/rustlib/etc`.
Rewrite associated types to use projection rather than dummy type parameters. This closes almost every (major) open issue, but I'm holding off on that until the code has landed and baked a bit. Probably it should have more tests, as well, but I wanted to get this landed as fast as possible so that we can collaborate on improving it.
The commit history is a little messy, particularly the merge commit at the end. If I get some time, I might just "reset" to the beginning and try to carve up the final state into logical pieces. Let me know if it seems hard to follow. By far the most crucial commit is "Implement associated type projection and normalization."
r? @nick29581
This commit adds support for the compiler to distinguish between different forms
of lookup paths in the compiler itself. Issue #19767 has some background on this
topic, as well as some sample bugs which can occur if these lookup paths are not
separated.
This commits extends the existing command line flag `-L` with the same trailing
syntax as the `-l` flag. Each argument to `-L` can now have a trailing `:all`,
`:native`, `:crate`, or `:dependency`. This suffix indicates what form of lookup
path the compiler should add the argument to. The `dependency` lookup path is
used when looking up crate dependencies, the `crate` lookup path is used when
looking for immediate dependencies (`extern crate` statements), and the `native`
lookup path is used for probing for native libraries to insert into rlibs. Paths
with `all` are used for all of these purposes (the default).
The default compiler lookup path (the rustlib libdir) is by default added to all
of these paths. Additionally, the `RUST_PATH` lookup path is added to all of
these paths.
Closes#19767
The first six commits are from an earlier PR (#19858) and have already been reviewed. This PR makes an awful hack in the compiler to accommodate slices both natively and in the index a range form. After a snapshot we can hopefully add the new Index impls and then we can remove these awful hacks.
r? @nikomatsakis (or anyone who knows the compiler, really)
This commit performs a second pass for stabilization over the `std::ptr` module.
The specific actions taken were:
* The `RawPtr` trait was renamed to `PtrExt`
* The `RawMutPtr` trait was renamed to `PtrMutExt`
* The module name `ptr` is now stable.
* These functions were all marked `#[stable]` with no modification:
* `null`
* `null_mut`
* `swap`
* `replace`
* `read`
* `write`
* `PtrExt::is_null`
* `PtrExt::is_not_null`
* `PtrExt::offset`
* These functions remain unstable:
* `as_ref`, `as_mut` - the return value of an `Option` is not fully expressive
as null isn't the only bad value, and it's unclear
whether we want to commit to these functions at this
time. The reference/lifetime semantics as written are
also problematic in how they encourage arbitrary
lifetimes.
* `zero_memory` - This function is currently not used at all in the
distribution, and in general it plays a broader role in the
"working with unsafe pointers" story. This story is not yet
fully developed, so at this time the function remains
unstable for now.
* `read_and_zero` - This function remains unstable for largely the same
reasons as `zero_memory`.
* These functions are now all deprecated:
* `PtrExt::null` - call `ptr::null` or `ptr::null_mut` instead.
* `PtrExt::to_uint` - use an `as` expression instead.
All of the current std::sync primitives have poisoning enable which means that
when a task fails inside of a write-access lock then all future attempts to
acquire the lock will fail. This strategy ensures that stale data whose
invariants are possibly not upheld are never viewed by other tasks to help
propagate unexpected panics (bugs in a program) among tasks.
Currently there is no way to test whether a mutex or rwlock is poisoned. One
method would be to duplicate all the methods with a sister foo_catch function,
for example. This pattern is, however, against our [error guidelines][errors].
As a result, this commit exposes the fact that a task has failed internally
through the return value of a `Result`.
[errors]: https://github.com/rust-lang/rfcs/blob/master/text/0236-error-conventions.md#do-not-provide-both-result-and-fail-variants
All methods now return a `LockResult<T>` or a `TryLockResult<T>` which
communicates whether the lock was poisoned or not. In a `LockResult`, both the
`Ok` and `Err` variants contains the `MutexGuard<T>` that is being returned in
order to allow access to the data if poisoning is not desired. This also means
that the lock is *always* held upon returning from `.lock()`.
A new type, `PoisonError`, was added with one method `into_guard` which can
consume the assertion that a lock is poisoned to gain access to the underlying
data.
This is a breaking change because the signatures of these methods have changed,
often incompatible ways. One major difference is that the `wait` methods on a
condition variable now consume the guard and return it in as a `LockResult` to
indicate whether the lock was poisoned while waiting. Most code can be updated
by calling `.unwrap()` on the return value of `.lock()`.
[breaking-change]
[breaking-change]
The `mut` in slices is now redundant. Mutability is 'inferred' from position. This means that if mutability is only obvious from the type, you will need to use explicit calls to the slicing methods.
This commit performs a second pass for stabilization over the `std::ptr` module.
The specific actions taken were:
* The `RawPtr` trait was renamed to `PtrExt`
* The `RawMutPtr` trait was renamed to `MutPtrExt`
* The module name `ptr` is now stable.
* These functions were all marked `#[stable]` with no modification:
* `null`
* `null_mut`
* `swap`
* `replace`
* `read`
* `write`
* `PtrExt::is_null`
* `PtrExt::offset`
* These functions remain unstable:
* `as_ref`, `as_mut` - the return value of an `Option` is not fully expressive
as null isn't the only bad value, and it's unclear
whether we want to commit to these functions at this
time. The reference/lifetime semantics as written are
also problematic in how they encourage arbitrary
lifetimes.
* `zero_memory` - This function is currently not used at all in the
distribution, and in general it plays a broader role in the
"working with unsafe pointers" story. This story is not yet
fully developed, so at this time the function remains
unstable for now.
* `read_and_zero` - This function remains unstable for largely the same
reasons as `zero_memory`.
* These functions are now all deprecated:
* `PtrExt::null` - call `ptr::null` or `ptr::null_mut` instead.
* `PtrExt::to_uint` - use an `as` expression instead.
* `PtrExt::is_not_null` - use `!p.is_null()` instead.
This commit is a second pass stabilization for the `std::comm` module,
performing the following actions:
* The entire `std::comm` module was moved under `std::sync::mpsc`. This movement
reflects that channels are just yet another synchronization primitive, and
they don't necessarily deserve a special place outside of the other
concurrency primitives that the standard library offers.
* The `send` and `recv` methods have all been removed.
* The `send_opt` and `recv_opt` methods have been renamed to `send` and `recv`.
This means that all send/receive operations return a `Result` now indicating
whether the operation was successful or not.
* The error type of `send` is now a `SendError` to implement a custom error
message and allow for `unwrap()`. The error type contains an `into_inner`
method to extract the value.
* The error type of `recv` is now `RecvError` for the same reasons as `send`.
* The `TryRecvError` and `TrySendError` types have had public reexports removed
of their variants and the variant names have been tweaked with enum
namespacing rules.
* The `Messages` iterator is renamed to `Iter`
This functionality is now all `#[stable]`:
* `Sender`
* `SyncSender`
* `Receiver`
* `std::sync::mpsc`
* `channel`
* `sync_channel`
* `Iter`
* `Sender::send`
* `Sender::clone`
* `SyncSender::send`
* `SyncSender::try_send`
* `SyncSender::clone`
* `Receiver::recv`
* `Receiver::try_recv`
* `Receiver::iter`
* `SendError`
* `RecvError`
* `TrySendError::{mod, Full, Disconnected}`
* `TryRecvError::{mod, Empty, Disconnected}`
* `SendError::into_inner`
* `TrySendError::into_inner`
This is a breaking change due to the modification of where this module is
located, as well as the changing of the semantics of `send` and `recv`. Most
programs just need to rename imports of `std::comm` to `std::sync::mpsc` and
add calls to `unwrap` after a send or a receive operation.
[breaking-change]
All of the current std::sync primitives have poisoning enable which means that
when a task fails inside of a write-access lock then all future attempts to
acquire the lock will fail. This strategy ensures that stale data whose
invariants are possibly not upheld are never viewed by other tasks to help
propagate unexpected panics (bugs in a program) among tasks.
Currently there is no way to test whether a mutex or rwlock is poisoned. One
method would be to duplicate all the methods with a sister foo_catch function,
for example. This pattern is, however, against our [error guidelines][errors].
As a result, this commit exposes the fact that a task has failed internally
through the return value of a `Result`.
[errors]: https://github.com/rust-lang/rfcs/blob/master/text/0236-error-conventions.md#do-not-provide-both-result-and-fail-variants
All methods now return a `LockResult<T>` or a `TryLockResult<T>` which
communicates whether the lock was poisoned or not. In a `LockResult`, both the
`Ok` and `Err` variants contains the `MutexGuard<T>` that is being returned in
order to allow access to the data if poisoning is not desired. This also means
that the lock is *always* held upon returning from `.lock()`.
A new type, `PoisonError`, was added with one method `into_guard` which can
consume the assertion that a lock is poisoned to gain access to the underlying
data.
This is a breaking change because the signatures of these methods have changed,
often incompatible ways. One major difference is that the `wait` methods on a
condition variable now consume the guard and return it in as a `LockResult` to
indicate whether the lock was poisoned while waiting. Most code can be updated
by calling `.unwrap()` on the return value of `.lock()`.
[breaking-change]
This commit is an implementation of [RFC 503][rfc] which is a stabilization
story for the prelude. Most of the RFC was directly applied, removing reexports.
Some reexports are kept around, however:
* `range` remains until range syntax has landed to reduce churn.
* `Path` and `GenericPath` remain until path reform lands. This is done to
prevent many imports of `GenericPath` which will soon be removed.
* All `io` traits remain until I/O reform lands so imports can be rewritten all
at once to `std::io::prelude::*`.
This is a breaking change because many prelude reexports have been removed, and
the RFC can be consulted for the exact list of removed reexports, as well as to
find the locations of where to import them.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0503-prelude-stabilization.md
[breaking-change]
Closes#20068