Commit Graph

83 Commits

Author SHA1 Message Date
Nadrieril 59031429c5 Separate `PlaceCtxt` from `UsefulnessCtxt` 2024-01-30 17:07:06 +01:00
Nadrieril 6ef836246b Make `PatternColumn` part of the public API 2024-01-30 17:06:52 +01:00
Nadrieril 83e88c6dfc Repurpose `MatchCtxt` for usefulness only 2024-01-30 17:06:51 +01:00
Nadrieril cb0e8c508c Limit the use of `PlaceCtxt` 2024-01-30 17:06:30 +01:00
Nadrieril 0b2579a1b6 Make `PatternColumn` generic in `Cx` 2024-01-30 16:57:44 +01:00
Laurențiu Nicola f5c78955c8 Stop using derivative in rustc_pattern_analysis 2024-01-27 14:21:01 +02:00
Matthias Krüger a37fa37281
Rollup merge of #118803 - Nadrieril:min-exhaustive-patterns, r=compiler-errors
Add the `min_exhaustive_patterns` feature gate

## Motivation

Pattern-matching on empty types is tricky around unsafe code. For that reason, current stable rust conservatively requires arms for empty types in all but the simplest case. It has long been the intention to allow omitting empty arms when it's safe to do so. The [`exhaustive_patterns`](https://github.com/rust-lang/rust/issues/51085) feature allows the omission of all empty arms, but hasn't been stabilized because that was deemed dangerous around unsafe code.

## Proposal

This feature aims to stabilize an uncontroversial subset of exhaustive_patterns. Namely: when `min_exhaustive_patterns` is enabled and the data we're matching on is guaranteed to be valid by rust's operational semantics, then we allow empty arms to be omitted. E.g.:

```rust
let x: Result<T, !> = foo();
match x { // ok
    Ok(y) => ...,
}
let Ok(y) = x; // ok
```

If the place is not guaranteed to hold valid data (namely ptr dereferences, ref dereferences (conservatively) and union field accesses), then we keep stable behavior i.e. we (usually) require arms for the empty cases.

```rust
unsafe {
    let ptr: *const Result<u32, !> = ...;
    match *ptr {
        Ok(x) => { ... }
        Err(_) => { ... } // still required
    }
}
let foo: Result<u32, &!> = ...;
match foo {
    Ok(x) => { ... }
    Err(&_) => { ... } // still required because of the dereference
}
unsafe {
    let ptr: *const ! = ...;
    match *ptr {} // already allowed on stable
}
```

Note that we conservatively consider that a valid reference can point to invalid data, hence we don't allow arms of type `&!` and similar cases to be omitted. This could eventually change depending on [opsem decisions](https://github.com/rust-lang/unsafe-code-guidelines/issues/413). Whenever opsem is undecided on a case, we conservatively keep today's stable behavior.

I proposed this behavior in the [`never_patterns`](https://github.com/rust-lang/rust/issues/118155) feature gate but it makes sense on its own and could be stabilized more quickly. The two proposals nicely complement each other.

## Unresolved Questions

Part of the question is whether this requires an RFC. I'd argue this doesn't need one since there is no design question beyond the intent to omit unreachable patterns, but I'm aware the problem can be framed in ways that require design (I'm thinking of the [original never patterns proposal](https://smallcultfollowing.com/babysteps/blog/2018/08/13/never-patterns-exhaustive-matching-and-uninhabited-types-oh-my/), which would frame this behavior as "auto-nevering" happening).

EDIT: I initially proposed a future-compatibility lint as part of this feature, I don't anymore.
2024-01-26 06:36:36 +01:00
Matthias Krüger a1ecced532
Rollup merge of #120318 - Nadrieril:share-debug-impl, r=compiler-errors
pattern_analysis: Reuse most of the `DeconstructedPat` `Debug` impl

The `DeconstructedPat: Debug` is best-effort because we'd need `tcx` to get things like field names etc. Since rust-analyzer has a similar constraint, this PR moves most the impl to be shared between the two. While I was at it I also fixed a nit in the `IntRange: Debug` impl.

r? `@compiler-errors`
2024-01-25 08:39:45 +01:00
Nadrieril 95a14d43d7 Implement feature gate logic 2024-01-25 00:12:32 +01:00
Nadrieril 354b45f528 Improve `Range: Debug` impl 2024-01-24 20:09:30 +01:00
Nadrieril bdab213993 Most of the `DeconstructedPat` `Debug` impl is reusable 2024-01-24 20:04:33 +01:00
Nadrieril e088016f9d Let `ctor_sub_tys` return any Iterator they want
Since we always clone and allocate the types somewhere else ourselves,
no need to ask for `Cx` to do the allocation.
2024-01-24 16:55:26 +01:00
Nicholas Nethercote e164cf30f8 Rename `TyCtxt::emit_spanned_lint` as `TyCtxt::emit_node_span_lint`. 2024-01-23 08:09:05 +11:00
Nadrieril 796cdc590c Remove Ty: Copy bound 2024-01-20 15:22:14 +01:00
Matthias Krüger 2587100a9b
Rollup merge of #119835 - Nadrieril:simplify-empty-logic, r=compiler-errors
Exhaustiveness: simplify empty pattern logic

The logic that handles empty patterns had gotten quite convoluted. This PR simplifies it a lot. I tried to make the logic as easy as possible to follow; this only does logically equivalent changes.

The first commit is a drive-by comment clarification that was requested after another PR a while back.

r? `@compiler-errors`
2024-01-19 19:27:00 +01:00
Matthias Krüger 3a3242a0f9
Rollup merge of #120039 - Nadrieril:remove-idx, r=compiler-errors
pat_analysis: Don't rely on contiguous `VariantId`s outside of rustc

Today's pattern_analysis uses `BitSet` and `IndexVec` on the provided enum variant ids, which only makes sense if these ids count the variants from 0. In rust-analyzer, the variant ids are global interning ids, which would make `BitSet` and `IndexVec` ridiculously wasteful. In this PR I add some shims to use `FxHashSet`/`FxHashMap` instead outside of rustc.

r? ```@compiler-errors```
2024-01-17 20:21:23 +01:00
Nadrieril 19d6f068ee Don't rely on contiguous `VariantId`s outside of rustc 2024-01-17 03:09:06 +01:00
Nadrieril 448c4a4efb Remove the unused `overlapping_range_endpoints` Vec 2024-01-15 19:27:06 +01:00
Nadrieril 8b66f497eb Lint overlapping ranges directly from exhaustiveness 2024-01-15 19:27:06 +01:00
Nadrieril d95644d3ae Simplify empty pattern logic some more 2024-01-15 16:56:18 +01:00
Nadrieril de77f1a86e Simplify empty pattern logic a bit 2024-01-15 16:56:18 +01:00
Nadrieril edb27a306a Make all the empty pattern decisions in `usefulness` 2024-01-15 16:56:18 +01:00
Nadrieril bf913ad0ae Simplify use of `ValidityConstraint`
We had reached a point where the shenanigans about omitting empty arms
are unnecessary.
2024-01-15 16:52:51 +01:00
Nadrieril db36304102 rustc_pattern_analysis no longer needs to be passed an arena 2024-01-12 18:55:27 +01:00
Nadrieril a24f4db41b Only lint ranges that really overlap 2024-01-11 14:04:11 +01:00
Nadrieril 6f6ba2571d Factor out collection of overlapping ranges 2024-01-11 13:59:41 +01:00
Nadrieril 89d01babe6 Track row intersections 2024-01-11 13:56:09 +01:00
bors 65b323b168 Auto merge of #119837 - matthiaskrgr:rollup-l2olpad, r=matthiaskrgr
Rollup of 11 pull requests

Successful merges:

 - #115046 (Use version-sorting for all sorting)
 - #118915 (Add some comments, add `can_define_opaque_ty` check to `try_normalize_ty_recur`)
 - #119006 (Fix is_global special address handling)
 - #119637 (Pass LLVM error message back to pass wrapper.)
 - #119715 (Exhaustiveness: abort on type error)
 - #119763 (Cleanup things in and around `Diagnostic`)
 - #119788 (change function name in comments)
 - #119790 (Fix all_trait* methods to return all traits available in StableMIR)
 - #119803 (Silence some follow-up errors [1/x])
 - #119804 (Stabilize mutex_unpoison feature)
 - #119832 (Meta: Add project const traits to triagebot config)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-01-11 02:10:34 +00:00
Nadrieril 4a1889e3fd Document the new `expand_and_push` method 2024-01-09 16:32:17 +01:00
Nadrieril 5c65e9fdaf Avoid `PatOrWild` glob import 2024-01-09 16:22:11 +01:00
Nadrieril 4b2e8bc841 Abort analysis on type error 2024-01-07 22:13:08 +01:00
Nadrieril 07d5f19426 Add an error path to the algorithm 2024-01-07 22:13:08 +01:00
Nadrieril 1a3edc169b We only need the arity of the subtype list now 2024-01-07 19:20:19 +01:00
Nadrieril 4ae2840e84 Use special enum to represent algorithm-generated wildcards in the matrix 2024-01-07 19:20:19 +01:00
Nadrieril 30ca1c0a5d Remove incorrect `assert`
It's incorrect because `CtorSet::split` returns a non-present
constructor into `present` in one specific case: variable-length slices
of an empty type. That's because empty constructors of arity 0 break the
algorithm. This is a tricky corner case that's hard to do cleanly. The
assert wasn't adding much anyway.
2024-01-07 16:45:44 +01:00
Nadrieril 4c2386137a Factor out pushing onto `PatternColumn` 2024-01-07 16:45:44 +01:00
Nadrieril 50b197c6ee Reuse `ctor_sub_tys` when we have one around 2024-01-06 18:03:13 +01:00
Nadrieril d40f1b1172 Remove `Matrix.wildcard_row`
It was only used to track types and relevancy, so may as well store that
directly.
2024-01-06 17:56:54 +01:00
bors 5bcd86d89b Auto merge of #119329 - Nadrieril:reveal-opaques-early, r=compiler-errors
Exhaustiveness: Statically enforce revealing of opaques

In https://github.com/rust-lang/rust/pull/116821 it was decided that exhaustiveness should operate on the hidden type of an opaque type when relevant. This PR makes sure we consistently reveal opaques within exhaustiveness. This makes it possible to remove `reveal_opaque_ty` from the `TypeCx` trait which was an unfortunate implementation detail.

r? `@compiler-errors`
2024-01-06 02:00:24 +00:00
Nicholas Nethercote 505c1371d0 Rename some `Diagnostic` setters.
`Diagnostic` has 40 methods that return `&mut Self` and could be
considered setters. Four of them have a `set_` prefix. This doesn't seem
necessary for a type that implements the builder pattern. This commit
removes the `set_` prefixes on those four methods.
2024-01-03 19:40:20 +11:00
Nadrieril c35272058d Statically enforce revealing of opaques 2024-01-01 23:10:03 +01:00
Michael Goulet fcb42b42d6 Remove movability from TyKind::Coroutine 2023-12-28 16:35:01 +00:00
Nadrieril fc0be3c921 Keep reference to the original `Pat` in `DeconstructedPat` 2023-12-26 23:14:23 +01:00
Michael Goulet e1be642b41
Rollup merge of #119307 - compiler-errors:pat-lifetimes, r=Nadrieril
Clean up some lifetimes in `rustc_pattern_analysis`

This PR removes some redundant lifetimes. I figured out that we were shortening the lifetime of an arena-allocated `&'p DeconstructedPat<'p>` to `'a DeconstructedPat<'p>`, which forced us to carry both lifetimes when we could otherwise carry just one.

This PR also removes and elides some unnecessary lifetimes.

I also cherry-picked 0292eb9bb9b897f5c0926c6a8530877f67e7cc9b, and then simplified more lifetimes in `MatchVisitor`, which should make #119233 a very simple PR!

r? Nadrieril
2023-12-26 13:29:14 -05:00
Michael Goulet 48d089a800 Merge 'thir and 'p 2023-12-26 03:15:41 +00:00
bors 2271c26e4a Auto merge of #119146 - nnethercote:rm-DiagCtxt-api-duplication, r=compiler-errors
Remove `DiagCtxt` API duplication

`DiagCtxt` defines the internal API for creating and emitting diagnostics: methods like `struct_err`, `struct_span_warn`, `note`, `create_fatal`, `emit_bug`. There are over 50 methods.

Some of these methods are then duplicated across several other types: `Session`, `ParseSess`, `Parser`, `ExtCtxt`, and `MirBorrowckCtxt`. `Session` duplicates the most, though half the ones it does are unused. Each duplicated method just calls forward to the corresponding method in `DiagCtxt`. So this duplication exists to (in the best case) shorten chains like `ecx.tcx.sess.parse_sess.dcx.emit_err()` to `ecx.emit_err()`.

This API duplication is ugly and has been bugging me for a while. And it's inconsistent: there's no real logic about which methods are duplicated, and the use of `#[rustc_lint_diagnostic]` and `#[track_caller]` attributes vary across the duplicates.

This PR removes the duplicated API methods and makes all diagnostic creation and emission go through `DiagCtxt`. It also adds `dcx` getter methods to several types to shorten chains. This approach scales *much* better than API duplication; indeed, the PR adds `dcx()` to numerous types that didn't have API duplication: `TyCtxt`, `LoweringCtxt`, `ConstCx`, `FnCtxt`, `TypeErrCtxt`, `InferCtxt`, `CrateLoader`, `CheckAttrVisitor`, and `Resolver`. These result in a lot of changes from `foo.tcx.sess.emit_err()` to `foo.dcx().emit_err()`. (You could do this with more types, but it gets into diminishing returns territory for types that don't emit many diagnostics.)

After all these changes, some call sites are more verbose, some are less verbose, and many are the same. The total number of lines is reduced, mostly because of the removed API duplication. And consistency is increased, because calls to `emit_err` and friends are always preceded with `.dcx()` or `.dcx`.

r? `@compiler-errors`
2023-12-26 02:24:39 +00:00
Michael Goulet 4ae024c754 Elide more lifetimes 2023-12-26 02:12:33 +00:00
Michael Goulet ae40f6a7ff Clean up more lifetimes 2023-12-26 02:06:39 +00:00
Michael Goulet b91a98ba10 Even more 2023-12-26 02:02:01 +00:00
Michael Goulet eebb2abe0b Yeet some lifetimes 2023-12-26 01:59:18 +00:00