| Age | Commit message (Collapse) | Author | Lines |
|
syntax: Unsupport `foo! bar { ... }` macros in the parser
Their support in expansion was removed in https://github.com/rust-lang/rust/pull/61606.
Also un-reserve `macro_rules` as a macro name, there's no ambiguity between `macro_rules` definitions and macro calls (it also wasn't reserved correctly).
cc https://github.com/rust-lang-nursery/wg-grammar/issues/51
|
|
wfcheck: resolve the type-vars in `AdtField` types
Normalization can leave some type-vars unresolved in its return type.
Make sure to resolve them so we have an infcx-independent type that can
be used with `needs_drop`.
Fixes #61402.
Closes #62212 - this PR fixes the root cause.
|
|
|
|
std: Move a process test out of libstd
This commit moves a test out of libstd which is causing deadlocks on
musl on CI. Looks like the recent update in musl versions brings in some
internal updates to musl which makes `setgid` and `setuid` invalid to
call after a `fork` in a multithreaded program. The issue seen here is
that the child thread was attempting to grab a lock held by a
nonexistent thread, meaning that the child process simply deadlocked
causing the whole test to deadlock.
This commit moves the test to its own file with no threads which should
work.
|
|
Don't store locals that have been moved from in generators
This avoids reserving storage in generators for locals that are moved
out of (and not re-initialized) prior to yield points. Fixes #59123.
This adds a new dataflow analysis, `RequiresStorage`, to determine whether the storage of a local can be destroyed without being observed by the program. The rules are:
1. StorageLive(x) => mark x live
2. StorageDead(x) => mark x dead
3. If a local is moved from, _and has never had its address taken_, mark it dead
4. If (any part of) a local is initialized, mark it live'
This is used to determine whether to save a local in the generator object at all, as well as which locals can be overlapped in the generator layout.
Here's the size in bytes of all testcases included in the change, before and after the change:
async fn test |Size before |Size after
-----------------|------------|----------
single | 1028 | 1028
single_with_noop | 2056 | 1032
joined | 5132 | 3084
joined_with_noop | 8208 | 3084
generator test |Size before |Size after
----------------------------|------------|----------
move_before_yield | 1028 | 1028
move_before_yield_with_noop | 2056 | 1032
overlap_move_points | 3080 | 2056
## Future work
Note that there is a possible extension to this optimization, which modifies rule 3 to read: "If a local is moved from, _**and either has never had its address taken, or is Freeze and has never been mutably borrowed**_, mark it dead." This was discussed at length in #59123 and then #61849. Because this would cause some behavior to be UB which was not UB before, it's a step that needs to be taken carefully.
A more immediate priority for me is inlining `std::mem::size_of_val(&x)` so it becomes apparent that the address of `x` is not taken. This way, using `size_of_val` to look at the size of your inner futures does not affect the size of your outer future.
cc @cramertj @eddyb @Matthias247 @nikomatsakis @RalfJung @Zoxc
|
|
Unreserve `macro_rules` as a macro name
|
|
Rollup of 8 pull requests
Successful merges:
- #62062 (Use a more efficient iteration order for forward dataflow)
- #62063 (Use a more efficient iteration order for backward dataflow)
- #62224 (rustdoc: remove unused derives and variants)
- #62228 (Extend the #[must_use] lint to boxed types)
- #62235 (Extend the `#[must_use]` lint to arrays)
- #62239 (Fix a typo)
- #62241 (Always parse 'async unsafe fn' + properly ban in 2015)
- #62248 (before_exec actually will only get deprecated with 1.37)
Failed merges:
r? @ghost
|
|
r=petrochenkov
Stabilize `type_alias_enum_variants` in Rust 1.37.0
Stabilize `#![feature(type_alias_enum_variants)]` which allows type-relative resolution with highest priority to `enum` variants in both expression and pattern contexts. For example, you may now write:
```rust
enum Option<T> {
None,
Some(T),
}
type OptAlias<T> = Option<T>;
fn work_on_alias(x: Option<u8>) -> u8 {
match x {
OptAlias::Some(y) => y + 1,
OptAlias::None => 0,
}
}
```
Closes https://github.com/rust-lang/rfcs/issues/2218
Closes https://github.com/rust-lang/rust/issues/52118
r? @petrochenkov
|
|
|
|
|
|
Normalization can leave some type-vars unresolved in its return type.
Make sure to resolve them so we have an infcx-independent type that can
be used with `needs_drop`.
Fixes #61402.
|
|
|
|
|
|
|
|
Closes #60709.
|
|
Remove `FnBox`
Remove `FnBox` since we now have `Box<dyn FnOnce>`.
Closes https://github.com/rust-lang/rust/issues/28796.
r? @cramertj
|
|
This commit moves a test out of libstd which is causing deadlocks on
musl on CI. Looks like the recent update in musl versions brings in some
internal updates to musl which makes `setgid` and `setuid` invalid to
call after a `fork` in a multithreaded program. The issue seen here is
that the child thread was attempting to grab a lock held by a
nonexistent thread, meaning that the child process simply deadlocked
causing the whole test to deadlock.
This commit moves the test to its own file with no threads which should
work.
|
|
Implement arbitrary_enum_discriminant
Implements RFC rust-lang/rfcs#2363 (tracking issue #60553).
|
|
Fix HIR visit order
Fixes #61442
When rustc::middle::region::ScopeTree computes its yield_in_scope
field, it relies on the HIR visitor order to properly compute which
types must be live across yield points. In order for the computed scopes
to agree with the generated MIR, we must ensure that expressions
evaluated before a yield point are visited before the 'yield'
expression.
However, the visitor order for ExprKind::AssignOp
was incorrect. The left-hand side of a compund assignment expression is
evaluated before the right-hand side, but the right-hand expression was
being visited before the left-hand expression. If the left-hand
expression caused a new type to be introduced (e.g. through a
deref-coercion), the new type would be incorrectly seen as occuring
*after* the yield point, instead of before. This leads to a mismatch
between the computed generator types and the MIR, since the MIR will
correctly see the type as being live across the yield point.
To fix this, we correct the visitor order for ExprKind::AssignOp
to reflect the actual evaulation order.
|
|
compiletest: Introduce `// {check,build,run}-pass` pass modes
Pass UI tests now have three modes
```
// check-pass
// build-pass
// run-pass
```
mirroring equivalent well-known `cargo` commands.
`// check-pass` will compile the test skipping codegen (which is expensive and isn't supposed to fail in most cases).
`// build-pass` will compile and link the test without running it.
`// run-pass` will compile, link and run the test.
Tests without a "pass" annotation are still considered "fail" tests.
Most UI tests would probably want to switch to `check-pass`.
Tests validating codegen would probably want to run the generated code as well and use `run-pass`.
`build-pass` should probably be rare (linking tests?).
https://github.com/rust-lang/rust/pull/61755 will provide a way to run the tests with any mode, e.g. bump `check-pass` tests to `run-pass` to satisfy especially suspicious people, and be able to make sure that codegen doesn't breaks in some entirely unexpected way.
Tests marked with any mode are expected to pass with any other mode, if that's not the case for some legitimate reason, then the test should be made a "fail" test rather than a "pass" test.
Perhaps some secondary CI can verify this invariant, but that's not super urgent.
`// compile-pass` still works and is equivalent to `build-pass`.
Why is `// compile-pass` bad - 1) it gives an impression that the test is only compiled, but not linked, 2) it doesn't mirror a cargo command.
It can be removed some time in the future in a separate PR.
cc https://github.com/rust-lang/rust/issues/61712
|
|
|
|
Compound operators (e.g. 'a += b') have two different possible
evaluation orders. When the left-hand side is a primitive type, the
expression is evaluated right-to-left. However, when the left-hand side
is a non-primitive type, the expression is evaluated left-to-right.
This causes problems when we try to determine if a type is live across a
yield point. Since we need to perform this computation before typecheck
has run, we can't simply check the types of the operands.
This commit calculates the most 'pessimistic' scenario - that is,
erring on the side of treating more types as live, rather than fewer.
This is perfectly safe - in fact, this initial liveness computation is
already overly conservative (e.g. issue #57478). The important thing is
that we compute a superset of the types that are actually live across
yield points. When we generate MIR, we'll determine which types actually
need to stay live across a given yield point, and which ones cam
actually be dropped.
Concretely, we force the computed HIR traversal index for
right-hand-side yield expression to be equal to the maximum index for
the left-hand side. This covers both possible execution orders:
* If the expression is evalauted right-to-left, our 'pessismitic' index
is unecessary, but safe. We visit the expressions in an
ExprKind::AssignOp from right to left, so it actually would have been
safe to do nothing. However, while increasing the index of a yield point
might cause the compiler to reject code that could actually compile, it
will never cause incorrect code to be accepted.
* If the expression is evaluated left-to-right, our 'pessimistic' index
correctly ensures that types in the left-hand-side are seen as occuring
before the yield - which is exactly what we want
|
|
Fixes #61442
When rustc::middle::region::ScopeTree ccomputes its yield_in_scope
field, it relies on the HIR visitor order to properly compute which
types must be live across yield points. In order for the computed scopes
to agree with the generated MIR, we must ensure that expressions
evaluated before a yield point are visited before the 'yield'
expression.
However, the visitor order for ExprKind::AssignOp
was incorrect. The left-hand side of a compund assignment expression is
evaluated before the right-hand side, but the right-hand expression was
being visited before the left-hand expression. If the left-hand
expression caused a new type to be introduced (e.g. through a
deref-coercion), the new type would be incorrectly seen as occuring
*after* the yield point, instead of before. This leads to a mismatch
between the computed generator types and the MIR, since the MIR will
correctly see the type as being live across the yield point.
To fix this, we correct the visitor order for ExprKind::AssignOp
to reflect the actual evaulation order.
|
|
|
|
|
|
|
|
|
|
|
|
Resolves #62007.
Due to a bug, the previous version of this check did not actually kill
any conflicting borrows unless the borrowed place had no projections.
Specifically, `entry_set` will always be empty when `statement_effect`
is called. It does not contain the set of borrows which are live at this
point in the program.
|
|
|
|
Rollup of 11 pull requests
Successful merges:
- #61505 (Only show methods that appear in `impl` blocks in the Implementors sections of trait doc pages)
- #61701 (move stray run-pass const tests into const/ folder)
- #61748 (Tweak transparent enums and unions diagnostic spans)
- #61802 (Make MaybeUninit #[repr(transparent)])
- #61839 (ci: Add a script for generating CPU usage graphs)
- #61842 (Remove unnecessary lift calls)
- #61843 (Turn down the myriad-closures test)
- #61896 (rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`.)
- #61898 (syntax: Factor out common fields from `SyntaxExtension` variants)
- #61938 (create an issue for miri even in status test-fail)
- #61941 (Preserve generator and yield source for error messages)
Failed merges:
r? @ghost
|
|
rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`.
Fixes #61882.
r? @petrochenkov cc @varkor
|
|
move stray run-pass const tests into const/ folder
r? @oli-obk
|
|
Refactor C FFI variadics to more closely match their C counterparts, and add Clone implementation
We had to make some changes to expose `va_copy` and `va_end` directly to users (mainly for C2Rust, but not exclusively):
- redefine the Rust variadic structures to more closely correspond to C: `VaList` now matches `va_list`, and `VaListImpl` matches `__va_list_tag`
- add `Clone` for `VaListImpl`
- add explicit `as_va_list()` conversion function from `VaListImpl` to `VaList`
- add deref coercion from `VaList` to `VaListImpl`
- add support for the `asmjs` target
All these changes were needed for use cases like:
```Rust
let mut ap2 = va_copy(ap);
vprintf(fmt, ap2);
va_end(&mut ap2);
```
|
|
|
|
Make use of `ptr::null(_mut)` instead of casting zero
There are few places that I don't replace the zero casting pointer with `ptr::null`
or `ptr::null_mut`:
```bash
% git grep -E '[ ([{]0 as \*'
src/libcore/ptr/mod.rs:216:pub const fn null<T>() -> *const T { 0 as *const T }
src/libcore/ptr/mod.rs:231:pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
src/test/run-pass/consts/const-cast-ptr-int.rs:12:static a: TestStruct = TestStruct{x: 0 as *const u8};
src/test/ui/issues/issue-45730.rs:5: let x: *const _ = 0 as *const _; //~ ERROR cannot cast
src/test/ui/issues/issue-45730.rs:8: let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast
src/test/ui/issues/issue-45730.stderr:14:LL | let x: *const _ = 0 as *const _;
src/test/ui/issues/issue-45730.stderr:24:LL | let x = 0 as *const i32 as *const _ as *mut _;
src/test/ui/lint/lint-forbid-internal-unsafe.rs:15: println!("{}", evil!(*(0 as *const u8)));
src/test/ui/order-dependent-cast-inference.rs:5: let mut y = 0 as *const _;
src/test/ui/order-dependent-cast-inference.stderr:4:LL | let mut y = 0 as *const _;
```
r? @sfackler
|
|
Clone for it.
|
|
test more variants of enum-int-casting
As I learned in https://github.com/rust-lang/rust/pull/61673#issuecomment-500213506, there is a code path we are not testing yet. Looks like enum-int-casting with and without an intermediate let-binding is totally different.
EDIT: The reason for this is to get rid of the cycle in definitions such as:
```rust
enum Foo {
A = 0,
B = Foo::A as isize + 2,
}
```
This has historically been supported, so a hack adding special treatment to `Enum::Variant as _` was added to keep supporting it.
|
|
|
|
|
|
|
|
|
|
Deprecate ONCE_INIT in future 1.38 release
Once::new() has been a stable const fn for a while now.
Closes #61746
|
|
Once::new() has been a stable const fn for a while now.
Closes #61746
|
|
Generator optimization: Overlap locals that never have storage live at the same time
The specific goal of this optimization is to optimize async fns which use `await!`. Notably, `await!` has an enclosing scope around the futures it awaits ([definition](https://github.com/rust-lang/rust/blob/08bfe16129b0621bc90184f8704523d4929695ef/src/libstd/macros.rs#L365-L381)), which we rely on to implement the optimization.
More generally, the optimization allows overlapping the storage of some locals which are never storage-live at the same time. **We care about storage-liveness when computing the layout, because knowing a field is `StorageDead` is the only way to prove it will not be accessed, either directly or through a reference.**
To determine whether we can overlap two locals in the generator layout, we look at whether they might *both* be `StorageLive` at any point in the MIR. We use the `MaybeStorageLive` dataflow analysis for this. We iterate over every location in the MIR, and build a bitset for each local of the locals it might potentially conflict with.
Next, we assign every saved local to one or more variants. The variants correspond to suspension points, and we include the set of locals live across a given suspension point in the variant. (Note that we use liveness instead of storage-liveness here; this ensures that the local has actually been initialized in each variant it has been included in. If the local is not live across a suspension point, then it doesn't need to be included in that variant.). It's important to note that the variants are a "view" into our layout.
For the layout computation, we use a simplified approach.
1. Start with the set of locals assigned to only one variant. The rest are disqualified.
2. For each pair of locals which may conflict *and are not assigned to the same variant*, we pick one local to disqualify from overlapping.
Disqualified locals go into a non-overlapping "prefix" at the beginning of our layout. This means they always have space reserved for them. All the locals that are allowed to overlap in each variant are then laid out after this prefix, in the "overlap zone".
So, if A and B were disqualified, and X, Y, and Z were all eligible for overlap, our generator might look something like this:
You can think of a generator as an enum, where some fields are shared between variants. e.g.
```rust
enum Generator {
Unresumed,
Poisoned,
Returned,
Suspend0(A, B, X),
Suspend1(B),
Suspend2(A, Y, Z),
}
```
where every mention of `A` and `B` refer to the same field, which does not move when changing variants. Note that `A` and `B` would automatically be sent to the prefix in this example. Assuming that `X` is never `StorageLive` at the same time as either `Y` or `Z`, it would be allowed to overlap with them.
Note that if two locals (`Y` and `Z` in this case) are assigned to the same variant in our generator, their memory would never overlap in the layout. Thus they can both be eligible for the overlapping section, even if they are storage-live at the same time.
---
Depends on:
- [x] #59897 Multi-variant layouts for generators
- [x] #60840 Preserve local scopes in generator MIR
- [x] #61373 Emit StorageDead along unwind paths for generators
Before merging:
- [x] ~Wrap the types of all generator fields in `MaybeUninitialized` in layout::ty::field~ (opened #60889)
- [x] Make PR description more complete (e.g. explain why storage liveness is important and why we have to check every location)
- [x] Clean up TODO
- [x] Fix the layout code to enforce that the same field never moves around in the generator
- [x] Add tests for async/await
- [x] ~Reduce # bits we store by half, since the conflict relation is symmetric~ (note: decided not to do this, for simplicity)
- [x] Store liveness information for each yield point in our `GeneratorLayout`, that way we can emit more useful debuginfo AND tell miri which fields are definitely initialized for a given variant (see discussion at https://github.com/rust-lang/rust/pull/59897#issuecomment-489468627)
|
|
Implement RFC 2645 (transparent enums and unions)
Tracking issue: #60405
|
|
Tracking issue: #60405
|
|
lexer: Disallow bare CR in raw byte strings
Handles bare CR ~but doesn't translate `\r\n` to `\n` yet in raw strings yet~ and translates CRLF to LF in raw strings.
As a side-note I think it'd be good to change the `unescape_` to return plain iterators to reduce some boilerplate (e.g. `has_error` could benefit from collecting `Result<T>` and aborting early on errors) but will do that separately, unless I missed something here that prevents it.
@matklad @petrochenkov thoughts?
|
|
|
|
Add nested 'yield' expression to weird expressions test
|