Commit graph

1816 commits

Author SHA1 Message Date
bors
ef119d704d Auto merge of #93028 - compiler-errors:const_drop_bounds, r=fee1-dead
Check `const Drop` impls considering `~const` Bounds

 This PR adds logic to trait selection to account for `~const` bounds in custom `impl const Drop` for types, elaborates the `const Drop` check in `rustc_const_eval` to check those bounds, and steals some drop linting fixes from #92922, thanks `@DrMeepster.`

r? `@fee1-dead` `@oli-obk` <sup>(edit: guess I can't request review from two people, lol)</sup>
since each of you wrote and reviewed #88558, respectively.

Since the logic here is more complicated than what existed, it's possible that this is a perf regression. But it works correctly with tests, and that makes me happy.

Fixes #92881
2022-01-24 08:05:37 +00:00
Matthias Krüger
8810af8082
Rollup merge of #93227 - compiler-errors:gat-hrtb-wfcheck, r=jackh726
Liberate late bound regions when collecting GAT substs in wfcheck

The issue here is that the [`GATSubstCollector`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_typeck/src/check/wfcheck.rs#L604) does not currently do anything wrt `Binder`s, so the GAT substs it copies out have escaping late bound regions when it walks through types like `for<'x> fn() -> Self::Gat<'x>`.

I made that visitor call `liberate_late_bound_regions`, not sure if that's the right thing here or we need to do something else to replace these bound vars with placeholders. I'm not familiar with other code doing anything similar.. But the issue is indeed no longer ICEing.

Fixes #92954

r? `@jackh726`
since you last touched this code, feel free to reassign
2022-01-23 20:13:06 +01:00
Michael Goulet
4a74ace3c9 Liberate late bound regions when collecting GAT substs in wfcheck 2022-01-23 09:41:52 -08:00
bors
d13e8dd41d Auto merge of #93165 - eholk:disable-generator-drop-tracking, r=nikomatsakis
Disable drop range tracking in generators

Generator drop tracking caused an ICE for generators involving the Never type (Issue #93161). Since this breaks a test case with miri, we temporarily disable drop tracking so miri is unblocked while we properly fix the issue.
2022-01-23 02:20:50 +00:00
Matthias Krüger
1f3a2dd0b1
Rollup merge of #92963 - terrarier2111:tuple-diagnostic, r=davidtwco
Implement tuple array diagnostic

Fixes https://github.com/rust-lang/rust/issues/92089
2022-01-21 22:03:16 +01:00
Matthias Krüger
430673f265
Rollup merge of #92843 - camelid:str-concat-sugg, r=davidtwco
Improve string concatenation suggestion

Before:

    error[E0369]: cannot add `&str` to `&str`
     --> file.rs:2:22
      |
    2 |     let _x = "hello" + " world";
      |              ------- ^ -------- &str
      |              |       |
      |              |       `+` cannot be used to concatenate two `&str` strings
      |              &str
      |
    help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
      |
    2 |     let _x = "hello".to_owned() + " world";
      |              ~~~~~~~~~~~~~~~~~~

After:

    error[E0369]: cannot add `&str` to `&str`
     --> file.rs:2:22
      |
    2 |     let _x = "hello" + " world";
      |              ------- ^ -------- &str
      |              |       |
      |              |       `+` cannot be used to concatenate two `&str` strings
      |              &str
      |
      = note: string concatenation requires an owned `String` on the left
    help: create an owned `String` from a string reference
      |
    2 |     let _x = "hello".to_owned() + " world";
      |                     +++++++++++
2022-01-21 22:03:15 +01:00
Eric Holk
ead84d0895 Add reference to breakage this works around 2022-01-21 11:06:14 -08:00
Eric Holk
13090889f5 Disable drop range tracking in generators
Generator drop tracking caused an ICE for generators involving the Never
type (Issue #93161). Since this breaks miri, we temporarily disable drop
tracking so miri is unblocked while we properly fix the issue.
2022-01-21 09:36:24 -08:00
Cameron Steffen
b11733534d Remove a span from hir::ExprKind::MethodCall 2022-01-21 07:48:10 -06:00
bors
523be2e05d Auto merge of #93138 - matthiaskrgr:rollup-m8akifd, r=matthiaskrgr
Rollup of 17 pull requests

Successful merges:

 - #91032 (Introduce drop range tracking to generator interior analysis)
 - #92856 (Exclude "test" from doc_auto_cfg)
 - #92860 (Fix errors on blanket impls by ignoring the children of generated impls)
 - #93038 (Fix star handling in block doc comments)
 - #93061 (Only suggest adding `!` to expressions that can be macro invocation)
 - #93067 (rustdoc mobile: fix scroll offset when jumping to internal id)
 - #93086 (Add tests to ensure that `let_chains` works with `if_let_guard`)
 - #93087 (Fix src/test/run-make/raw-dylib-alt-calling-convention)
 - #93091 (⬆ chalk to 0.76.0)
 - #93094 (src/test/rustdoc-json: Check for `struct_field`s in `variant_tuple_struct.rs`)
 - #93098 (Show a more informative panic message when `DefPathHash` does not exist)
 - #93099 (rustdoc: auto create output directory when "--output-format json")
 - #93102 (Pretty printer algorithm revamp step 3)
 - #93104 (Support --bless for pp-exact pretty printer tests)
 - #93114 (update comment for `ensure_monomorphic_enough`)
 - #93128 (Add script to prevent point releases with same number as existing ones)
 - #93136 (Backport the 1.58.1 release notes to master)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
2022-01-21 03:04:43 +00:00
Matthias Krüger
b8df581ef8
Rollup merge of #93114 - lcnr:mk_array, r=RalfJung
update comment for `ensure_monomorphic_enough`

r? `@RalfJung`
2022-01-20 23:37:42 +01:00
Matthias Krüger
3d10c64b26
Rollup merge of #91032 - eholk:generator-drop-tracking, r=nikomatsakis
Introduce drop range tracking to generator interior analysis

This PR addresses cases such as this one from #57478:
```rust
struct Foo;
impl !Send for Foo {}

let _: impl Send = || {
    let guard = Foo;
    drop(guard);
    yield;
};
```

Previously, the `generator_interior` pass would unnecessarily include the type `Foo` in the generator because it was not aware of the behavior of `drop`. We fix this issue by introducing a drop range analysis that finds portions of the code where a value is guaranteed to be dropped. If a value is dropped at all suspend points, then it is no longer included in the generator type. Note that we are using "dropped" in a generic sense to include any case in which a value has been moved. That is, we do not only look at calls to the `drop` function.

There are several phases to the drop tracking algorithm, and we'll go into more detail below.
1. Use `ExprUseVisitor` to find values that are consumed and borrowed.
2. `DropRangeVisitor` uses consume and borrow information to gather drop and reinitialization events, as well as build a control flow graph.
3. We then propagate drop and reinitialization information through the CFG until we reach a fix point (see `DropRanges::propagate_to_fixpoint`).
4. When recording a type (see `InteriorVisitor::record`), we check the computed drop ranges to see if that value is definitely dropped at the suspend point. If so, we skip including it in the type.

## 1. Use `ExprUseVisitor` to find values that are consumed and borrowed.

We use `ExprUseVisitor` to identify the places where values are consumed. We track both the `hir_id` of the value, and the `hir_id` of the expression that consumes it. For example, in the expression `[Foo]`, the `Foo` is consumed by the array expression, so after the array expression we can consider the `Foo` temporary to be dropped.

In this process, we also collect values that are borrowed. The reason is that the MIR transform for generators conservatively assumes anything borrowed is live across a suspend point (see `rustc_mir_transform::generator::locals_live_across_suspend_points`). We match this behavior here as well.

## 2. Gather drop events, reinitialization events, and control flow graph

After finding the values of interest, we perform a post-order traversal over the HIR tree to find the points where these values are dropped or reinitialized. We use the post-order index of each event because this is how the existing generator interior analysis refers to the position of suspend points and the scopes of variables.

During this traversal, we also record branching and merging information to handle control flow constructs such as `if`, `match`, and `loop`. This is necessary because values may be dropped along some control flow paths but not others.

## 3. Iterate to fixed point

The previous pass found the interesting events and locations, but now we need to find the actual ranges where things are dropped. Upon entry, we have a list of nodes ordered by their position in the post-order traversal. Each node has a set of successors. For each node we additionally keep a bitfield with one bit per potentially consumed value. The bit is set if we the value is dropped along all paths entering this node.

To compute the drop information, we first reverse the successor edges to find each node's predecessors. Then we iterate through each node, and for each node we set its dropped value bitfield to the intersection of all incoming dropped value bitfields.

If any bitfield for any node changes, we re-run the propagation loop again.

## 4. Ignore dropped values across suspend points

At this point we have a data structure where we can ask whether a value is guaranteed to be dropped at any post order index for the HIR tree. We use this information in `InteriorVisitor` to check whether a value in question is dropped at a particular suspend point. If it is, we do not include that value's type in the generator type.

Note that we had to augment the region scope tree to include all yields in scope, rather than just the last one as we did before.

r? `@nikomatsakis`
2022-01-20 23:37:29 +01:00
Matthias Krüger
db1253f1d2
Rollup merge of #92582 - lcnr:generic-arg-infer, r=BoxyUwU
improve `_` constants in item signature handling

removing the "type" from the error messages does slightly worsen the error messages for types, but figuring out whether the placeholder is for a type or a constant and correctly dealing with that seemed fairly difficult to me so I took the easy way out  Imo the error message is still clear enough.

r? `@BoxyUwU` cc `@estebank`
2022-01-20 17:10:35 +01:00
Matthias Krüger
413f490677
Rollup merge of #92183 - tmandry:issue-74256, r=estebank
Point at correct argument when async fn output type lifetime disagrees with signature

Fixes most of #74256.

## Problems fixed

This PR fixes a couple of related problems in the error reporting code.

### Highlighting the wrong argument

First, the error reporting code was looking at the desugared return type of an `async fn` to decide which parameter to highlight. For example, a function like

```rust
async fn async_fn(self: &Struct, f: &u32) -> &u32
{ f }
```

desugars to

```rust
async fn async_fn<'a, 'b>(self: &'a Struct, f: &'b u32)
-> impl Future<Output = &'a u32> + 'a + 'b
{ f }
```

Since `f: &'b u32` is returned but the output type is `&'a u32`, the error would occur when checking that `'a: 'b`.

The reporting code would look to see if the "offending" lifetime `'b` was included in the return type, and because the code was looking at the desugared future type, it was included. So it defaulted to reporting that the source of the other lifetime `'a` (the `self` type) was the problem, when it was really the type of `f`. (Note that if it had chosen instead to look at `'a` first, it too would have been included in the output type, and it would have arbitrarily reported the error (correctly this time) on the type of `f`.)

Looking at the actual future type isn't useful for this reason; it captures all input lifetimes. Using the written return type for `async fn` solves this problem and results in less confusing error messages for the user.

This isn't a perfect fix, unfortunately; writing the "manually desugared" form of the above function still results in the wrong parameter being highlighted. Looking at the output type of every `impl Future` return type doesn't feel like a very principled approach, though it might work. The problem would remain for function signatures that look like the desugared one above but use different traits. There may be deeper changes required to pinpoint which part of each type is conflicting.

### Lying about await point capture causing lifetime conflicts

The second issue fixed by this PR is the unnecessary complexity in `try_report_anon_anon_conflict`. It turns out that the root cause I suggested in https://github.com/rust-lang/rust/issues/76547#issuecomment-692863608 wasn't really the root cause. Adding special handling to report that a variable was captured over an await point only made the error messages less correct and pointed to a problem other than the one that actually occurred.

Given the above discussion, it's easy to see why: `async fn`s capture all input lifetimes in their return type, so holding an argument across an await point should never cause a lifetime conflict! Removing the special handling simplified the code and improved the error messages (though they still aren't very good!)

## Future work

* Fix error reporting on the "desugared" form of this code
* Get the `suggest_adding_lifetime_params` suggestion firing on these examples
  * cc #42703, I think

r? `@estebank`
2022-01-20 17:10:34 +01:00
lcnr
c29b637875 update comments 2022-01-20 14:50:35 +01:00
Michael Goulet
b7e4433974 Foreign types are trivially drop
- Also rename a trivial_const_drop to match style of other functions in
  the util module.
- Also add a test for `const Drop` that doesn't depend on a `~const`
  bound.
- Also comment a bit why we remove the const bound during dropck impl
  check.
2022-01-19 20:07:04 -08:00
Tyler Mandry
6487845884 Properly account for binders in get_impl_future_output_ty 2022-01-19 21:33:57 +00:00
lcnr
4bd571c4ff remove is_noop 2022-01-19 13:58:29 +01:00
Noah Lev
7c4eca0687 Make suggestions verbose 2022-01-18 16:38:06 -08:00
Noah Lev
7507fb6306 Shorten and improve messages 2022-01-18 16:32:58 -08:00
Eric Holk
76f6b57125 Fix build after rebase 2022-01-18 14:42:39 -08:00
Eric Holk
d840d0c62e Use .. patterns in cfg_build.rs 2022-01-18 14:25:31 -08:00
Eric Holk
e0a5370ef0 Respond to code review comments 2022-01-18 14:25:31 -08:00
Eric Holk
32930d9ea7 Safely handle partial drops
We previously weren't tracking partial re-inits while being too
aggressive around partial drops. With this change, we simply ignore
partial drops, which is the safer, more conservative choice.
2022-01-18 14:25:30 -08:00
Eric Holk
78c5644de5 drop_ranges: Add TrackedValue enum
This makes it clearer what values we are tracking and why.
2022-01-18 14:25:30 -08:00
Eric Holk
787f4cbd15 Handle uninhabited return types
This changes drop range analysis to handle uninhabited return types such
as `!`. Since these calls to these functions do not return, we model
them as ending in an infinite loop.
2022-01-18 14:25:30 -08:00
Eric Holk
f730bd0dad Track changed bitsets in CFG propagation
This reduces the amount of work done, especially in later iterations,
by only processing nodes whose predecessors changed in the previous
iteration, or earlier in the current iteration. This also has the side
effect of completely ignoring all unreachable nodes.
2022-01-18 14:25:29 -08:00
Eric Holk
7d11b336f3 Remove clones and most allocations from propagate_to_fixpoint 2022-01-18 14:25:29 -08:00
Eric Holk
a7df4e8d2f Handle empty loops better 2022-01-18 14:25:29 -08:00
Eric Holk
6e281a7782 Explicitly list all ExprKinds in cfg_build
Also rearranges the existing arms to be more logical. For example, Break
and Continue come closer to Loop now.
2022-01-18 14:25:29 -08:00
Eric Holk
4a70de7932 Handle reinits in match guards 2022-01-18 14:25:29 -08:00
Eric Holk
2af02cf2c4 More comments and refactoring
The refactoring mainly keeps the separation between the modules clearer.
For example, process_deferred_edges function moved to cfg_build.rs since
that is really part of building the CFG, not finding the fixpoint.

Also, we use PostOrderId instead of usize in a lot more places now.
2022-01-18 14:25:28 -08:00
Eric Holk
6a28afb2a3 Fixing formatting 2022-01-18 14:25:28 -08:00
Eric Holk
9347bf498a Additional cleanup
This cleans up the refactoring from the previous patch and cleans things
up a bit. Each module has a clear entry point and everything else is
private.
2022-01-18 14:25:28 -08:00
Eric Holk
f5f98d7ee4 Refactor drop_ranges
Splits drop_ranges into drop_ranges::record_consumed_borrow,
drop_ranges::cfg_build, and drop_ranges::cfg_propagate. The top level
drop_ranges module has an entry point that does all the coordination of
the other three phases, using code original in generator_interior.
2022-01-18 14:25:27 -08:00
Eric Holk
30e1b1e92e Address code review comments
1. Add test case for partial drops
2. Simplify code in `propagate_to_fixpoint` and remove most clones
3. Clean up PostOrderIndex creation
2022-01-18 14:25:27 -08:00
Eric Holk
006f547162 Add more comments 2022-01-18 14:25:27 -08:00
Eric Holk
5feb4d0106 Refactor code to keep most drop range analysis in drop_ranges.rs 2022-01-18 14:25:27 -08:00
Eric Holk
904c270149 More comments and small cleanups 2022-01-18 14:25:26 -08:00
Eric Holk
b39fb9bb7b Fix control flow handling in generator_interior
All tests pass now! The issue was that we weren't handling all edges
correctly, but now they are handled consistently.

This includes code to dump a graphviz file for the CFG we built for drop
tracking.

Also removes old DropRanges tests.
2022-01-18 14:25:26 -08:00
Eric Holk
c7afaa1686 Handle break and continue. Change fixpoint computation to handle unreachable nodes. 2022-01-18 14:25:26 -08:00
Eric Holk
ff0e8f4ba2 Revamped DropRange data structure
Not currently working. Need to flow drop information.
2022-01-18 14:25:26 -08:00
Eric Holk
ba7d12731e More tracing and tests 2022-01-18 14:25:25 -08:00
Eric Holk
457415294c Handle more cases with conditionally initialized/dropped values 2022-01-18 14:25:25 -08:00
Eric Holk
298ca2f679 Basic loop support 2022-01-18 14:25:25 -08:00
Eric Holk
96117701f9 Support reinitialization of variables 2022-01-18 14:25:25 -08:00
Eric Holk
aa029d4bbe Support conditional drops
This adds support for branching and merging control flow and uses this
to correctly handle the case where a value is dropped in one branch of
an if expression but not another.

There are other cases we need to handle, which will come in follow up
patches.

Issue #57478
2022-01-18 14:25:24 -08:00
Eric Holk
f246c0b116 Attribute drop to parent expression of the consume point
This is needed to handle cases like `[a, b.await, c]`. `ExprUseVisitor`
considers `a` to be consumed when it is passed to the array, but the
array is not quite live yet at that point. This means we were missing
the `a` value across the await point. Attributing drops to the parent
expression means we do not consider the value consumed until the
consuming expression has finished.

Issue #57478
2022-01-18 14:25:24 -08:00
Eric Holk
f664cfc47c Make generator and async-await tests pass
The main change needed to make this work is to do a pessimistic over-
approximation for AssignOps. The existing ScopeTree analysis in
region.rs works by doing both left to right and right to left order and
then choosing the most conservative ordering. This behavior is needed
because AssignOp's evaluation order depends on whether it is a primitive
type or an overloaded operator, which runs as a method call.

This change mimics the same behavior as region.rs in
generator_interior.rs.

Issue #57478
2022-01-18 14:25:24 -08:00
Eric Holk
c4dee40170 Track drops across multiple yields 2022-01-18 14:25:24 -08:00