Use PlaceRef projection abstractions more consistently in rustc_mir
PlaceRef contains abstractions for dealing with the `projections` array. This PR uses these abstractions more consistently within the `rustc_mir` crate.
See associated issue: rust-lang/rust#80647.
r? `@RalfJung`
Improve diagnostics when closure doesn't meet trait bound
Improves the diagnostics when closure doesn't meet trait bound by modifying `TypeckResuts::closure_kind_origins` such that `hir::Place` is used instead of `Symbol`. Using `hir::Place` to describe which capture influenced the decision of selecting a trait a closure satisfies to (Fn/FnMut/FnOnce, Copy) allows us to show precise path in the diagnostics when `capture_disjoint_field` feature is enabled.
Closes rust-lang/project-rfc-2229/issues/21
r? ```@nikomatsakis```
correctly deal with late-bound lifetimes in anon consts
adds support for using late bound lifetimes of the parent context in anon consts.
```rust
#![feature(const_generics)]
const fn inner<'a>() -> usize where &'a (): Sized { 3 }
fn test<'a>() {
let _: [u8; inner::<'a>()];
}
```
The lifetime `'a` is late bound in `test` so it's not included in its generics but is instead dealt with separately in borrowck.
This didn't previously work for anon consts as they have to use the late bound lifetimes of their parent which has
to be explicitly handled.
r? ```@matthewjasper``` cc ```@varkor``` ```@eddyb```
Rollup of 17 pull requests
Successful merges:
- #78455 (Introduce {Ref, RefMut}::try_map for optional projections in RefCell)
- #80144 (Remove giant badge in README)
- #80614 (Explain why borrows can't be held across yield point in async blocks)
- #80670 (TrustedRandomAaccess specialization composes incorrectly for nested iter::Zips)
- #80681 (Clarify what the effects of a 'logic error' are)
- #80764 (Re-stabilize Weak::as_ptr and friends for unsized T)
- #80901 (Make `x.py --color always` apply to logging too)
- #80902 (Add a regression test for #76281)
- #80941 (Do not suggest invalid code in pattern with loop)
- #80968 (Stabilize the poll_map feature)
- #80971 (Put all feature gate tests under `feature-gates/`)
- #81021 (Remove doctree::Import)
- #81040 (doctest: Reset errors before dropping the parse session)
- #81060 (Add a regression test for #50041)
- #81065 (codegen_cranelift: Fix redundant semicolon warn)
- #81069 (Add sample code for Rc::new_cyclic)
- #81081 (Add test for #34792)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
implement ptr::write without dedicated intrinsic
This makes `ptr::write` more consistent with `ptr::write_unaligned`, `ptr::read`, `ptr::read_unaligned`, all of which are implemented in terms of `copy_nonoverlapping`.
This means we can also remove `move_val_init` implementations in codegen and Miri, and its special handling in the borrow checker.
Also see [this Zulip discussion](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/ptr.3A.3Aread.20vs.20ptr.3A.3Awrite).
Use better ICE message when no MIR is available
The ICE message is somewhat confusing and overly specific - the issue is
that there's no MIR available.
This should make debugging these ICEs easier since the error tells you
what's actually wrong, not what it was trying to do when it failed.
cc https://github.com/rust-lang/rust/pull/80952#issuecomment-759198841
cc `````@jyn514`````
The ICE message is somewhat confusing and overly specific - the issue is
that there's no MIR available.
This should make debugging these ICEs easier since the error tells you
what's actually wrong, not what it was trying to do when it failed.
cc https://github.com/rust-lang/rust/pull/80952#issuecomment-759198841
Separate out a `hir::Impl` struct
This makes it possible to pass the `Impl` directly to functions, instead
of having to pass each of the many fields one at a time. It also
simplifies matches in many cases.
See `rustc_save_analysis::dump_visitor::process_impl` or `rustdoc::clean::clean_impl` for a good example of how this makes `impl`s easier to work with.
r? `@petrochenkov` maybe?
This makes it possible to pass the `Impl` directly to functions, instead
of having to pass each of the many fields one at a time. It also
simplifies matches in many cases.
Make CTFE able to check for UB...
... by not doing any optimizations on the `const fn` MIR used in CTFE. This means we duplicate all `const fn`'s MIR now, once for CTFE, once for runtime. This PR is for checking the perf effect, so we have some data when talking about https://github.com/rust-lang/const-eval/blob/master/rfcs/0000-const-ub.md
To do this, we now have two queries for obtaining mir: `optimized_mir` and `mir_for_ctfe`. It is now illegal to invoke `optimized_mir` to obtain the MIR of a const/static item's initializer, an array length, an inline const expression or an enum discriminant initializer. For `const fn`, both `optimized_mir` and `mir_for_ctfe` work, the former returning the MIR that LLVM should use if the function is called at runtime. Similarly it is illegal to invoke `mir_for_ctfe` on regular functions.
This is all checked via appropriate assertions and I don't think it is easy to get wrong, as there should be no `mir_for_ctfe` calls outside the const evaluator or metadata encoding. Almost all rustc devs should keep using `optimized_mir` (or `instance_mir` for that matter).
Explain method-call move errors in loops
PR #73708 added a more detailed explanation of move errors that occur
due to a call to a method that takes `self`. This PR extends that logic
to work when a move error occurs due to a method call in the previous
iteration of a loop.
Add ABI argument for called function in `find_mir_or_eval_fn` and
`call_extra_fn`. Useful for comparing with expected ABI in interpreters.
Related to [miri/1631](https://github.com/rust-lang/miri/issues/1631)
PR #73708 added a more detailed explanation of move errors that occur
due to a call to a method that takes `self`. This PR extends that logic
to work when a move error occurs due to a method call in the previous
iteration of a loop.
MIR Inline is incompatible with coverage
Fixes: #80060
Fixed by disabling inlining if `-Zinstrument-coverage` is set.
The PR also adds additional use cases to the coverage test for doctests.
r? `@wesleywiser`
cc: `@tmandry`
Make `ExpnData` fields `krate` and `orig_id` private
These fields are only used by hygiene serialized, and should not be
accessed by anything outside of `rustc_span`.
use PlaceRef more consistently instead of loosely coupled local+projection
Instead of working directly with the `projections` array, use `iter_projections` and `last_projection`. This avoids having to construct new `PlaceRef` from the pieces everywhere.
I only did this for a few files, to see how people think about this. If y'all are happy with this, I'll open an E-mentor issue to complete this. I grepped for `Place::ty_from` to find the places that need adjusting -- this could miss some, but I am not sure what else to grep for.
Allow references to interior mutable data behind a feature gate
supercedes #80373 by simply not checking for interior mutability on borrows of locals that have `StorageDead` and thus can never be leaked to the final value of the constant
tracking issue: https://github.com/rust-lang/rust/issues/80384
r? `@RalfJung`
Some Promotion Refactoring
Clean up promotion a bit:
* factor out some common code
* more exhaustive matches
This *should* not break anything... the only potentially-breaking change is that `BorrowKind::Shallow | BorrowKind::Unique` are now rejected for internal references.
r? ``@oli-obk``
Rollup of 7 pull requests
Successful merges:
- #80185 (Fix ICE when pointing at multi bytes character)
- #80260 (slightly more typed interface to panic implementation)
- #80311 (Improvements to NatVis support)
- #80337 (Use `desc` as a doc-comment for queries if there are no doc comments)
- #80381 (Revert "Cleanup markdown span handling")
- #80492 (remove empty wraps, don't return Results from from infallible functions)
- #80509 (where possible, pass slices instead of &Vec or &String (clippy::ptr_arg))
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
validate promoteds
Turn on const-value validation for promoteds. This is made possible now that https://github.com/rust-lang/rust/issues/67534 is resolved.
I don't think this is a breaking change. We don't promote any unsafe operation any more (since https://github.com/rust-lang/rust/pull/77526 landed). We *do* promote `const fn` calls under some circumstances (in `const`/`static` initializers), but union field access and similar operations are not allowed in `const fn`. So now is a perfect time to add this check. :D
r? `@oli-obk`
Fixes https://github.com/rust-lang/rust/issues/67465
Remap instrument-coverage line numbers in doctests
This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done, and rustdoc
still does not output the correct filename when running doctests in a
workspace.
Part of #79417 although I dont consider that fixed until both filenames
and columns are mapped correctly.
r? `@richkadel`
I might jump on zulip the comming days. Still need to figure out how to properly write tests for this, and deal with other doctest issues in the meantime.
Acknowledge that `[CONST; N]` is stable
When `const_in_array_repeat_expressions` (RFC 2203) got unstably implemented as part of https://github.com/rust-lang/rust/pull/61749, accidentally, the special case of repeating a *constant* got stabilized immediately. That is why the following code works on stable:
```rust
const EMPTY: Vec<i32> = Vec::new();
pub const fn bar() -> [Vec<i32>; 2] {
[EMPTY; 2]
}
fn main() {
let x = bar();
}
```
In contrast, if we had written `[expr; 2]` for some expression that is not *literally* a constant but could be evaluated at compile-time (e.g. `(EMPTY,).0`), this would have failed.
We could take back this stabilization as it was clearly accidental. However, I propose we instead just officially accept this and stabilize a small subset of RFC 2203, while leaving the more complex case of general expressions that could be evaluated at compile-time unstable. Making that case work well is pretty much blocked on inline `const` expressions (to avoid relying too much on [implicit promotion](https://github.com/rust-lang/const-eval/blob/master/promotion.md)), so it could take a bit until it comes to full fruition. `[CONST; N]` is an uncontroversial subset of this feature that has no semantic ambiguities, does not rely on promotion, and basically provides the full expressive power of RFC 2203 but without the convenience (people have to define constants to repeat them, possibly using associated consts if generics are involved).
Well, I said "no semantic ambiguities", that is only almost true... the one point I am not sure about is `[CONST; 0]`. There are two possible behaviors here: either this is equivalent to `let x = CONST; [x; 0]`, or it is a NOP (if we argue that the constant is never actually instantiated). The difference between the two is that if `CONST` has a destructor, it should run in the former case (but currently doesn't, due to https://github.com/rust-lang/rust/issues/74836); but should not run if it is considered a NOP. For regular `[x; 0]` there seems to be consensus on running drop (there isn't really an alternative); any opinions for the `CONST` special case? Should this instantiate the const only to immediately run its destructors? That seems somewhat silly to me. After all, the `let`-expansion does *not* work in general, for `N > 1`.
Cc `@rust-lang/lang` `@rust-lang/wg-const-eval`
Cc https://github.com/rust-lang/rust/issues/49147
Make BoundRegion have a kind of BoungRegionKind
Split from #76814
Also includes making `replace_escaping_bound_vars` only return `T`
Going to r? `@lcnr`
Feel free to reassign
Prefer regions with an `external_name` in `approx_universal_upper_bound`
Fixes#75785
When displaying a MIR borrowcheck error, we may need to find an upper
bound for a region, which gives us a region to point to in the error
message. However, a region might outlive multiple distinct universal
regions, in which case the only upper bound is 'static
To try to display a meaningful error message, we compute an
'approximate' upper bound by picking one of the universal regions.
Currently, we pick the region with the lowest index - however, this
caused us to produce a suboptimal error message in issue #75785
This PR `approx_universal_upper_bound` to prefer regions with an
`external_name`. This causes us to prefer regions from function
arguments/upvars, which seems to lead to a nicer error message in some
cases.
Fixes#75785
When displaying a MIR borrowcheck error, we may need to find an upper
bound for a region, which gives us a region to point to in the error
message. However, a region might outlive multiple distinct universal
regions, in which case the only upper bound is 'static
To try to display a meaningful error message, we compute an
'approximate' upper bound by picking one of the universal regions.
Currently, we pick the region with the lowest index - however, this
caused us to produce a suboptimal error message in issue #75785
This PR `approx_universal_upper_bound` to prefer regions with an
`external_name`. This causes us to prefer regions from function
arguments/upvars, which seems to lead to a nicer error message in some
cases.
Move binder for dyn to each list item
This essentially changes `ty::Binder<&'tcx List<ExistentialTraitRef>>` to `&'tcx List<ty::Binder<ExistentialTraitRef>>`.
This is a first step in moving the `dyn Trait` representation closer to Chalk, which we've talked about in `@rust-lang/wg-traits.`
r? `@nikomatsakis`
Always run intrinsics lowering pass
Move intrinsics lowering pass from the optimization phase (where it
would not run if -Zmir-opt-level=0), to the drop lowering phase where it
runs unconditionally.
The implementation of those intrinsics in code generation and
interpreter is unnecessary. Remove it.
Fixed conflict with drop elaboration and coverage
See
https://github.com/rust-lang/rust/issues/80045#issuecomment-745733339
Coverage statements are moved to the beginning of the BCB. This does
also affect what's counted before a panic, changing some results, but I
think these results may even be preferred? In any case, there are no
guarantees about what's counted when a panic occurs (by design).
r? `@tmandry`
FYI `@wesleywiser` `@ecstatic-morse`
Fix issue #78496
EarlyOtherwiseBranch finds MIR structures like:
```
bb0: {
...
_2 = discriminant(X)
...
switchInt(_2) -> [1_isize: bb1, otherwise: bb3]
}
bb1: {
...
_3 = discriminant(Y)
...
switchInt(_3) -> [1_isize: bb2, otherwise: bb3]
}
bb2: {...}
bb3: {...}
```
And transforms them into something like:
```
bb0: {
...
_2 = discriminant(X)
_3 = discriminant(Y)
_4 = Eq(_2, _3)
switchInt(_4) -> [true: bb4, otherwise: bb3]
}
bb2: {...} // unchanged
bb3: {...} // unchanged
bb4: {
switchInt(_2) -> [1_isize: bb2, otherwise: bb3]
}
```
But that is not always a safe thing to do -- sometimes the early `otherwise` branch is necessary so the later block could assume the value of `discriminant(X)`.
I am not totally sure what's the best way to detect that, but fixing #78496 should be easy -- we just check if `X` is a sub-expression of `Y`. A more precise test might be to check if `Y` contains a `Downcast(1)` of `X`, but I think this might be good enough.
Fix#78496
See
https://github.com/rust-lang/rust/issues/80045#issuecomment-745733339
Coverage statements are moved to the beginning of the BCB. This does
also affect what's counted before a panic, changing some results, but I
think these results may even be preferred? In any case, there are no
guarantees about what's counted when a panic occurs (by design).
make MIR graphviz generation use gsgdt
gsgdt [https://crates.io/crates/gsgdt] is a crate which provides an
interface for stringly typed graphs. It also provides generation of
graphviz dot format from said graph.
This is the first in a series of PRs on moving graphviz code out of rustc into normal crates and then implementating graph diffing on top of these crates.
r? `@oli-obk`
Fixes reported bugs in Rust Coverage
Fixes: #79569Fixes: #79566Fixes: #79565
For the first issue (#79569), I got hit a `debug_assert!()` before
encountering the reported error message (because I have `debug = true`
enabled in my config.toml).
The assertion showed me that some `SwitchInt`s can have more than one
target pointing to the same `BasicBlock`.
I had thought that was invalid, but since it seems to be possible, I'm
allowing this now.
I added a new test for this.
----
In the last two cases above, both tests (intentionally) fail to compile,
but the `InstrumentCoverage` pass is invoked anyway.
The MIR starts with an `Unreachable` `BasicBlock`, which I hadn't
encountered before. (I had assumed the `InstrumentCoverage` pass
would only be invoked with MIRs from successful compilations.)
I don't have test infrastructure set up to test coverage on files that
fail to compile, so I didn't add a new test.
r? `@tmandry`
FYI: `@wesleywiser`
consider assignments of union field of ManuallyDrop type safe
Assigning to `Copy` union fields is safe because that assignment will never drop anything. However, with https://github.com/rust-lang/rust/pull/77547, unions may also have `ManuallyDrop` fields, and their assignments are currently still unsafe. That seems unnecessary though, as assigning `ManuallyDrop` does not drop anything either, and is thus safe even for union fields.
I assume this will at least require FCP.
[mir-opt] Allow debuginfo to be generated for a constant or a Place
Prior to this commit, debuginfo was always generated by mapping a name
to a Place. This has the side-effect that `SimplifyLocals` cannot remove
locals that are only used for debuginfo because their other uses have
been const-propagated.
To allow these locals to be removed, we now allow debuginfo to point to
a constant value. The `ConstProp` pass detects when debuginfo points to
a local with a known constant value and replaces it with the value. This
allows the later `SimplifyLocals` pass to remove the local.
Move intrinsics lowering pass from the optimization phase (where it
would not run if -Zmir-opt-level=0), to the drop lowering phase where it
runs unconditionally.
The implementation of those intrinsics in code generation and
interpreter is unnecessary. Remove it.
Adds checks for:
* `no_core` attribute
* explicitly-enabled `legacy` symbol mangling
* mir_opt_level > 1 (which enables inlining)
I removed code from the `Inline` MIR pass that forcibly disabled
inlining if `-Zinstrument-coverage` was set. The default `mir_opt_level`
does not enable inlining anyway. But if the level is explicitly set and
is greater than 1, I issue a warning.
The new warnings show up in tests, which is much better for diagnosing
potential option conflicts in these cases.
Remove an unused dependency that made `rustdoc` crash
Whilst struggling with https://github.com/rust-lang/rust/issues/79980 I discovered that this dependency was unused, and that made rustdoc crash. This PR removes it.
fix more clippy::complexity findings
fix clippy::unnecessary_filter_map
use if let Some(x) = .. instead of ...map(|x|) to conditionally run fns that return () (clippy::option_map_unit_fn)
fix clippy::{needless_bool, manual_unwrap_or}
don't clone types that are copy (clippy::clone_on_copy)
don't convert types into identical types with .into() (clippy::useless_conversion)
use strip_prefix over slicing (clippy::manual_strip)
r? ``@Dylan-DPC``
Fixes: #79569Fixes: #79566Fixes: #79565
For the first issue (#79569), I got hit a `debug_assert!()` before
encountering the reported error message (because I have `debug = true`
enabled in my config.toml).
The assertion showed me that some `SwitchInt`s can have more than one
target pointing to the same `BasicBlock`.
I had thought that was invalid, but since it seems to be possible, I'm
allowing this now.
I added a new test for this.
----
In the last two cases above, both tests (intentionally) fail to compile,
but the `InstrumentCoverage` pass is invoked anyway.
The MIR starts with an `Unreachable` `BasicBlock`, which I hadn't
encountered before. (I had assumed the `InstrumentCoverage` pass
would only be invoked with MIRs from successful compilations.)
I don't have test infrastructure set up to test coverage on files that
fail to compile, so I didn't add a new test.
Capture precise paths in THIR and MIR
This PR allows THIR and MIR to use the result of the new capture analysis to actually capture precise paths
To achieve we:
- Writeback min capture results to TypeckResults
- Move handling upvars to PlaceBuilder in mir_build
- Lower precise paths in THIR build by reading min_captures
- Search for ancestors in min_capture when trying to build a MIR place which starts off of an upvar
Closes: https://github.com/rust-lang/project-rfc-2229/issues/10
Partly implements: rust-lang/project-rfc-2229#18
Work that remains (not in this PR):
- [ ] [Known bugs when feature gate is enabled](https://github.com/rust-lang/project-rfc-2229/projects/1?card_filter_query=label%3Abug)
- [ ] Use min_capure_map for
- [ ] Liveness analysis
- [ ] rustc_mir/interpret/validity.rs
- [ ] regionck
- [ ] rust-lang/project-rfc-2229#8
- [ ] remove closure_captures and upvar_capture_map
r? `@ghost`