Fix overflow checking in unsigned pow()
The pow() method for unsigned integers produced 0 instead of trapping overflow for certain inputs. Calls such as 2u32.pow(1024) produced 0 when they should trap an overflow. This also adds tests for the correctly handling overflow in unsigned pow().
This was previously fixed for signed integers in #28248, but it seems unsigned integers got missed that time.
For issue number #34913
Remove data structure specialization for .zip() iterator
Go back on half the specialization, the part that changed the Zip
struct's fields themselves depending on the types of the iterators.
Previous PR: #33090
This means that the Zip iterator will always carry two usize fields,
which are sometimes unused. If a whole for loop using a .zip() iterator is
inlined, these are simply removed and have no effect.
The same improvement for Zip of for example slice iterators remain, and
they still optimize well. However, like when the specialization of zip
was merged, the compiler is still very sensistive to the exact context.
For example this code only autovectorizes if the function is used, not
if the code in zip_sum_i32 is inserted inline where it was called:
```rust
fn zip_sum_i32(xs: &[i32], ys: &[i32]) -> i32 {
let mut s = 0;
for (&x, &y) in xs.iter().zip(ys) {
s += x * y;
}
s
}
fn zipdot_i32_default_zip(b: &mut test::Bencher)
{
let xs = vec![1; 1024];
let ys = vec![1; 1024];
b.iter(|| {
zip_sum_i32(&xs, &ys)
})
}
```
Include a test that checks that `Zip<T, U>` is covariant w.r.t. T and U.
Fixes#35727
Avoid loading and parsing unconfigured non-inline modules.
For example, `#[cfg(any())] mod foo;` will always compile after this PR, even if `foo.rs` and `foo/mod.rs` do not exist or do not contain valid Rust.
Fixes#36478 and fixes#27873.
r? @nrc
trans: Let the collector find drop-glue for all vtables, not just VTableImpl.
This fixes#36260. So far, the collector has only recorded drop-glue for insertion into a vtable if the vtable was for an impl. But there's actually no reason why it shouldn't do just the same for closure vtables, afaict.
r? @eddyb
cc @rust-lang/compiler
The wording of RFC #495 enables moves out of slices. Unfortuantely, non-zeroing
moves out of slices introduce a very annoying complication: as slices can
vary in their length, indexes from the start and end may or may not overlap
depending on the slice's exact length, which prevents assigning a particular
drop flag for each individual element.
For example, in the code
```Rust
fn foo<T>(a: Box<[Box<[T]>]>, c: bool) -> T {
match (a, c) {
(box [box [t, ..], ..], true) => t,
(box [.., box [.., t]], false) => t,
_ => panic!()
}
}
```
If the condition is false, we have to drop the first element
of `a`, unless `a` has size 1 in which case we drop all the elements
of it but the last.
If someone comes with a nice way of handling it, we can always re-allow
moves out of slices.
This is a [breaking-change], but it is behind the `slice_patterns` feature
gate and was not allowed until recently.
Be more specific when type parameter shadows primitive type
When a type parameter shadows a primitive type, the error message
was non obvious. For example, given the file `file.rs`:
```rust
trait Parser<T> {
fn parse(text: &str) -> Option<T>;
}
impl<bool> Parser<bool> for bool {
fn parse(text: &str) -> Option<bool> {
Some(true)
}
}
fn main() {
println!("{}", bool::parse("ok").unwrap_or(false));
}
```
The output was:
```bash
% rustc file.rs
error[E0308]: mismatched types
--> file.rs:7:14
|
7 | Some(true)
| ^^^^ expected type parameter, found bool a
|
= note: expected type `bool`
= note: found type `bool`
error: aborting due to previous error
```
We now show extra information about the type:
```bash
% rustc file.rs
error[E0308]: mismatched types
--> file.rs:7:14
|
7 | Some(true)
| ^^^^ expected type parameter, found bool a
|
= note: expected type `bool` (type parameter)
= note: found type `bool` (bool)
error: aborting due to previous error
```
Fixes#35030
When a type parameter shadows a primitive type, the error message
was non obvious. For example, given the file `file.rs`:
```rust
trait Parser<T> {
fn parse(text: &str) -> Option<T>;
}
impl<bool> Parser<bool> for bool {
fn parse(text: &str) -> Option<bool> {
Some(true)
}
}
fn main() {
println!("{}", bool::parse("ok").unwrap_or(false));
}
```
The output was:
```bash
% rustc file.rs
error[E0308]: mismatched types
--> file.rs:7:14
|
7 | Some(true)
| ^^^^ expected type parameter, found bool
|
= note: expected type `bool`
= note: found type `bool`
error: aborting due to previous error
```
We now show extra information about the type:
```bash
% rustc file.rs
error[E0308]: mismatched types
--> file.rs:7:14
|
7 | Some(true)
| ^^^^ expected type parameter, found bool
|
= note: expected type `bool` (type parameter)
= note: found type `bool` (bool)
error: aborting due to previous error
```
Fixes#35030
clear obligations-added flag with nested fulfillcx
This flag is a debugging measure designed to detect cases where we start
a snapshot, create type variables, register obligations involving those
type variables in the fulfillment cx, and then have to unroll the
snapshot, leaving "dangling type variables" behind. HOWEVER, in some
cases the flag is wrong. In particular, we sometimes create a
"mini-fulfilment-cx" in which we enroll obligations. As long as this
fulfillment cx is fully drained before we return, this is not a problem,
as there won't be any escaping obligations in the main cx. So we add a
fn to save/restore the flag.
Fixes#36053.
r? @arielb1
invoke drop glue with a ptr to (data, meta)
This is done by creating a little space on the stack. Hokey, but it's the simplest fix I can see, and I am in "kill regressions" mode right now.
Fixes#35546
r? @eddyb
Use primitive indexing in slice's Index/IndexMut
[T]'s Index implementation is normally not used for indexing, instead
the compiler supplied indexing is used.
Use the compiler supplied version in Index/IndexMut.
This removes an inconsistency:
Compiler supplied bound check failures look like this:
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 4'
If you convince Rust to use the Index impl for slices, bounds check
failure looks like this instead:
thread 'main' panicked at 'assertion failed: index < self.len()'
The latter is used if you for example use Index generically:
```rust
use std::ops::Index;
fn foo<T: ?Sized>(x: &T) where T: Index<usize> { &x[4]; }
foo(&[1, 2, 3][..])
```
Assign node ids during macro expansion
After this PR,
- The `ExtCtxt` can access `resolve`'s `Resolver` through the trait object `ext::base::Resolver`.
- The `Resolver` trait object can load macros and replaces today's `MacroLoader` trait object.
- The macro expander uses the `Resolver` trait object to resolve macro invocations.
- The macro expander assigns node ids and builds the `Resolver`'s `macros_at_scope` map.
- This is groundwork for merging import resolution and expansion.
- Performance of expansion together with node id assignment improves by ~5%.
**EDIT:** Since Github is reordering the commits, here is `git log`:
- b54e1e3997: Differentiate between monotonic and non-monotonic expansion and only assign node ids during monotonic expansion.
- 78c0039878: Expand generated test harnesses and macro registries.
- f3c2dca353: Remove scope placeholders from the crate root.
- c86c8d41a2: Perform node id assignment and `macros_at_scope` construction during the `InvocationCollector` and `PlaceholderExpander` folds.
- 72a636975f: Move macro resolution into `librustc_resolve`.
- 20b43b2323: Rewrite the unit tests in `ext/expand.rs` as a `compile-fail` test.
- a9821e1658: Refactor `ExtCtxt` to use a `Resolver` instead of a `MacroLoader`.
- 60440b226d: Refactor `noop_fold_stmt_kind` out of `noop_fold_stmt`.
- 50f94f6c95: Avoid needless reexpansions.
r? @nrc
Fix indeterminism in ty::TraitObject representation.
Make sure that projection bounds in `ty::TraitObject` are sorted in a way that is stable across compilation sessions and crate boundaries.
This PR
+ moves `DefPathHashes` up into `librustc` so it can be used there to create a stable sort key for `DefId`s,
+ changes `PolyExistentialProjection::sort_key()` to take advantage of the above,
+ and removes the unused `PolyProjectionPredicate::sort_key()` and `ProjectionTy::sort_key()` methods.
Fixes#36155
Improve shallow `Clone` deriving
`Copy` unions now support `#[derive(Clone)]`.
Less code is generated for `#[derive(Clone, Copy)]`.
+
Unions now support `#[derive(Eq)]`.
Less code is generated for `#[derive(Eq)]`.
---
Example of code reduction:
```
enum E {
A { a: u8, b: u16 },
B { c: [u8; 100] },
}
```
Before:
```
fn clone(&self) -> E {
match (&*self,) {
(&E::A { a: ref __self_0, b: ref __self_1 },) => {
::std::clone::assert_receiver_is_clone(&(*__self_0));
::std::clone::assert_receiver_is_clone(&(*__self_1));
*self
}
(&E::B { c: ref __self_0 },) => {
::std::clone::assert_receiver_is_clone(&(*__self_0));
*self
}
}
}
```
After:
```
fn clone(&self) -> E {
{
let _: ::std::clone::AssertParamIsClone<u8>;
let _: ::std::clone::AssertParamIsClone<u16>;
let _: ::std::clone::AssertParamIsClone<[u8; 100]>;
*self
}
}
```
All the matches are removed, bound assertions are more lightweight.
`let _: Checker<CheckMe>;`, unlike `checker(&check_me);`, doesn't have to be translated by rustc_trans and then inlined by LLVM, it doesn't even exist in MIR, this means faster compilation.
---
Union impls are generated like this:
```
union U {
a: u8,
b: u16,
c: [u8; 100],
}
```
```
fn clone(&self) -> U {
{
let _: ::std::clone::AssertParamIsCopy<Self>;
*self
}
}
```
Fixes https://github.com/rust-lang/rust/issues/36043
cc @durka
r? @alexcrichton
Go back on half the specialization, the part that changed the Zip
struct's fields themselves depending on the types of the iterators.
This means that the Zip iterator will always carry two usize fields,
which are unused. If a whole for loop using a .zip() iterator is
inlined, these are simply removed and have no effect.
The same improvement for Zip of for example slice iterators remain, and
they still optimize well. However, like when the specialization of zip
was merged, the compiler is still very sensistive to the exact context.
For example this code only autovectorizes if the function is used, not
if the code in zip_sum_i32 is inserted inline it was called:
```
fn zip_sum_i32(xs: &[i32], ys: &[i32]) -> i32 {
let mut s = 0;
for (&x, &y) in xs.iter().zip(ys) {
s += x * y;
}
s
}
fn zipdot_i32_default_zip(b: &mut test::Bencher)
{
let xs = vec![1; 1024];
let ys = vec![1; 1024];
b.iter(|| {
zip_sum_i32(&xs, &ys)
})
}
```
Include a test that checks that Zip<T, U> is covariant w.r.t. T and U.
Inherit overflow checks for sum and product
We have previously documented the fact that these will panic on overflow, but I think this behavior is what people actually want/expect. `#[rustc_inherit_overflow_checks]` didn't exist when we discussed these for stabilization.
r? @alexcrichton
Closes#35807
[T]'s Index implementation is normally not used for indexing, instead
the compiler supplied indexing is used.
Use the compiler supplied version in Index/IndexMut.
This removes an inconsistency:
Compiler supplied bound check failures look like this:
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 4'
If you convince Rust to use the Index impl for slices, bounds check
failure looks like this instead:
thread 'main' panicked at 'assertion failed: index < self.len()'
The latter is used if you for example use Index generically::
use std::ops::Index;
fn foo<T: ?Sized>(x: &T) where T: Index<usize> { &x[4]; }
foo(&[1, 2, 3][..])
This flag is a debugging measure designed to detect cases where we start
a snapshot, create type variables, register obligations involving those
type variables in the fulfillment cx, and then have to unroll the
snapshot, leaving "dangling type variables" behind. HOWEVER, in some
cases the flag is wrong. In particular, we sometimes create a
"mini-fulfilment-cx" in which we enroll obligations. As long as this
fulfillment cx is fully drained before we return, this is not a problem,
as there won't be any escaping obligations in the main cx. So we add a
fn to save/restore the flag.
rustdoc: Don't add extra newlines for fully opaque structs
Changes the definition for braced structs with only private or hidden fields to save space on the page.
Before:
```
pub struct Vec<T> {
// some fields omitted
}
```
After:
```
pub struct Vec<T> { /* fields omitted */ }
```
This also cleans up empty braced structs.
Before:
```
pub struct Foo {
}
```
After:
```
pub struct Foo {}
```
[before](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html) [after](https://ollie27.github.io/rust_doc_test/std/vec/struct.Vec.html)
cc #34713
crate-ify compiler-rt into compiler-builtins
libcompiler-rt.a is dead, long live libcompiler-builtins.rlib
This commit moves the logic that used to build libcompiler-rt.a into a
compiler-builtins crate on top of the core crate and below the std crate.
This new crate still compiles the compiler-rt instrinsics using gcc-rs
but produces an .rlib instead of a static library.
Also, with this commit rustc no longer passes -lcompiler-rt to the
linker. This effectively makes the "no-compiler-rt" field of target
specifications a no-op. Users of `no_std` will have to explicitly add
the compiler-builtins crate to their crate dependency graph *if* they
need the compiler-rt intrinsics - this is a [breaking-change]. Users
of the `std` have to do nothing extra as the std crate depends
on compiler-builtins.
Finally, this a step towards lazy compilation of std with Cargo as the
compiler-rt intrinsics can now be built by Cargo instead of having to
be supplied by the user by some other method.
closes#34400
---
r? @alexcrichton
core: add likely and unlikely intrinsics
I'm no good at reading assembly, but I have tried a stage1 compiler with this patch, and it does cause different asm output. Additionally, testing this compiler on my httparse crate with some `likely` usage added in to the branches does affect benchmarks. However, I'm sure a codegen test should be included, if anyone knows what it should look like.
There isn't an entry in `librustc_trans/context.rs` in this diff, because it already exists (`llvm.expect.i1` is used for array indices).
----
Even though this does affect httparse benchmarks, it doesn't seem to affect it the same way GCC's `__builtin_expect` affects picohttpparser. I was confused that the deviation on the benchmarks grew hugely when testing this, especially since I'm absolutely certain that the branchs where I added `likely` were always `true`. I chalk that up to GCC and LLVM handle branch prediction differently.
cc #26179
Zero first byte of CString on drop
Hi! This is one more attempt to ameliorate `CString::new("...").unwrap().as_ptr()` problem (related RFC: https://github.com/rust-lang/rfcs/pull/1642).
One of the biggest problems with this code is that it may actually work in practice, so the idea of this PR is to proactively break such invalid code.
Looks like writing a `null` byte at the start of the CString should do the trick, and I think is an affordable cost: zeroing a single byte in `Drop` should be cheap enough compared to actual memory deallocation which would follow.
I would actually prefer to do something like
```Rust
impl Drop for CString {
fn drop(&mut self) {
let pattern = b"CTHULHU FHTAGN ";
let bytes = self.inner[..self.inner.len() - 1];
for (d, s) in bytes.iter_mut().zip(pattern.iter().cycle()) {
*d = *s;
}
}
}
```
because Cthulhu error should be much easier to google, but unfortunately this would be too expensive in release builds, and we can't implement things `cfg(debug_assertions)` conditionally in stdlib.
Not sure if the whole idea or my implementation (I've used ~~`transmute`~~ `mem::unitialized` to workaround move out of Drop thing) makes sense :)