summary refs log tree commit diff
path: root/compiler/rustc_borrowck/src
AgeCommit message (Collapse)AuthorLines
2024-01-30Auto merge of #119101 - compiler-errors:outlives, r=lcnrbors-9/+28
Normalize region obligation in lexical region resolution with next-gen solver This normalizes region obligations when we `resolve_regions`, since they may be unnormalized with deferred projection equality. It's pretty hard to add tests that exercise this without also triggering MIR borrowck errors (because we don't normalize there yet). I've added one test with two revisions that should test that we both 1. normalize region obligations in the param env, and 2. normalize registered region obligations during lexical region resolution.
2024-01-30Rollup merge of #120488 - nnethercote:diag-lifetimes, r=oli-obkGuillaume Gomez-1/+1
Diagnostic lifetimes cleanups Some diagnostic simplifications. r? `@oli-obk`
2024-01-30Remove the lifetime from `DiagnosticArgValue`.Nicholas Nethercote-1/+1
Because it's almost always static. This makes `impl IntoDiagnosticArg for DiagnosticArgValue` trivial, which is nice. There are a few diagnostics constructed in `compiler/rustc_mir_build/src/check_unsafety.rs` and `compiler/rustc_mir_transform/src/errors.rs` that now need symbols converted to `String` with `to_string` instead of `&str` with `as_str`, but that' no big deal, and worth it for the simplifications elsewhere.
2024-01-30Apply suggestions from reviewMichael Goulet-10/+28
2024-01-30Normalize caller boundsMichael Goulet-1/+2
2024-01-29Rollup merge of #120390 - matthewjasper:inline-constant-pat-mir, r=davidtwcoDylan DPC-8/+56
Borrow check inline const patterns Add type annotations to MIR so that borrowck can pass constraints from inline constants in patterns to the containing function. Also enables some inline constant pattern tests that were fixed by the THIR unsafeck stabilization. cc #76001
2024-01-29Borrow check inline const patternsMatthew Jasper-8/+56
Add type annotations to MIR so that borrowck can pass constraints from inline constants in patterns to the containing function.
2024-01-29Stop using `String` for error codes.Nicholas Nethercote-6/+8
Error codes are integers, but `String` is used everywhere to represent them. Gross! This commit introduces `ErrCode`, an integral newtype for error codes, replacing `String`. It also introduces a constant for every error code, e.g. `E0123`, and removes the `error_code!` macro. The constants are imported wherever used with `use rustc_errors::codes::*`. With the old code, we have three different ways to specify an error code at a use point: ``` error_code!(E0123) // macro call struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call \#[diag(name, code = "E0123")] // string struct Diag; ``` With the new code, they all use the `E0123` constant. ``` E0123 // constant struct_span_code_err!(dcx, span, E0123, "msg"); // constant \#[diag(name, code = E0123)] // constant struct Diag; ``` The commit also changes the structure of the error code definitions: - `rustc_error_codes` now just defines a higher-order macro listing the used error codes and nothing else. - Because that's now the only thing in the `rustc_error_codes` crate, I moved it into the `lib.rs` file and removed the `error_codes.rs` file. - `rustc_errors` uses that macro to define everything, e.g. the error code constants and the `DIAGNOSTIC_TABLES`. This is in its new `codes.rs` file.
2024-01-25Remove unused featuresclubby789-3/+0
2024-01-23Auto merge of #116152 - cjgillot:unchunck, r=nnethercotebors-3/+3
Only use dense bitsets in dataflow analyses When a dataflow state has the size close to the number of locals, we should prefer a dense bitset, like we already store locals in a dense vector. Other occurrences of `ChunkedBitSet` need to be justified by the size of the dataflow state.
2024-01-22Remove uses of HybridBitSet.Camille GILLOT-3/+3
2024-01-23Rename `TyCtxt::emit_spanned_lint` as `TyCtxt::emit_node_span_lint`.Nicholas Nethercote-1/+1
2024-01-20Auto merge of #120003 - Mark-Simulacrum:opt-promoted, r=davidtwcobors-30/+87
perf: Don't track specific live points for promoteds We don't query this information out of the promoted (it's basically a single "unit" regardless of the complexity within it) and this saves on re-initializing the SparseIntervalMatrix's backing IndexVec with mostly empty rows for all of the leading regions in the function. Typical promoteds will only contain a few regions that need up be uplifted, while the parent function can have thousands. For a simple function repeating println!("Hello world"); 50,000 times this reduces compile times from 90 to 15 seconds in debug mode. The previous implementations re-initialization led to an overall roughly n^2 runtime as each promoted initialized slots for ~n regions, now we scale closer to linearly (5000 hello worlds takes 1.1 seconds). cc https://github.com/rust-lang/rust/issues/50994, https://github.com/rust-lang/rust/issues/86244
2024-01-20Rollup merge of #120155 - compiler-errors:no-erased-when-promoting, r=aliemjayMatthias Krüger-5/+9
Don't use `ReErased` to detect type test promotion failed Using `ReErased` here is convenient because it implicitly stores the state that we are explicitly recording with the `failed` variable now, but I also think it adds a tiny bit of complexity that is not worth it. r? `@aliemjay`
2024-01-20Don't use ReErased to detect type test promotion failedMichael Goulet-5/+9
2024-01-19perf: Don't track specific live points for promotedsMark Rousskov-30/+87
We don't query this information out of the promoted (it's basically a single "unit" regardless of the complexity within it) and this saves on re-initializing the SparseIntervalMatrix's backing IndexVec with mostly empty rows for all of the leading regions in the function. Typical promoteds will only contain a few regions that need up be uplifted, while the parent function can have thousands. For a simple function repeating println!("Hello world"); 50,000 times this reduces compile times from 90 to 15 seconds in debug mode. The previous implementations re-initialization led to an overall roughly n^2 runtime as each promoted initialized slots for ~n regions, now we scale closer to linearly (5000 hello worlds takes 1.1 seconds).
2024-01-19Rollup merge of #120126 - sjwang05:issue-102269, r=compiler-errorsMatthias Krüger-7/+90
Suggest `.swap()` when encountering conflicting borrows from `mem::swap` on a slice This PR modifies the existing suggestion by matching on `[ProjectionElem::Deref, ProjectionElem::Index(_)]` instead of just `[ProjectionElem::Index(_)]`, which caused us to miss many cases. Additionally, it adds a more specific, machine-applicable suggestion in the case we determine `mem::swap` was used to swap elements in a slice. Closes #102269
2024-01-19Suggest .swap() instead of mem::swap() in more casessjwang05-7/+92
2024-01-17Rollup merge of #115291 - cjgillot:dest-prop-save, r=JakobDegenMatthias Krüger-114/+32
Save liveness results for DestinationPropagation `DestinationPropagation` needs to verify that merge candidates do not conflict with each other. This is done by verifying that a local is not live when its counterpart is written to. To get the liveness information, the pass runs `MaybeLiveLocals` dataflow analysis repeatedly, once for each propagation round. This is quite costly, and the main driver for the perf impact on `ucd` and `diesel`. (See https://github.com/rust-lang/rust/pull/115105#issuecomment-1689205908) In order to mitigate this cost, this PR proposes to save the result of the analysis into a `SparseIntervalMatrix`, and mirror merges of locals into that matrix: `liveness(destination) := liveness(destination) union liveness(source)`. <details> <summary>Proof</summary> We denote by `'` all the quantities of the transformed program. Let $\varphi$ be a mapping of locals, which maps `source` to `destination`, and is identity otherwise. The exact liveness set after a statement is $out'(statement)$, and the proposed liveness set is $\varphi(out(statement))$. Consider a statement. Suppose that the output state verifies $out' \subset phi(out)$. We want to prove that $in' \subset \varphi(in)$ where $in = (out - kill) \cup gen$, and conclude by induction. We have 2 cases: either that statement is kept with locals renumbered by $\varphi$, or it is a tautological assignment and it removed. 1. If the statement is kept: the gen-set and the kill-set of $statement' = \varphi(statement)$ are $gen' = \varphi(gen)$ and $kill' = \varphi(kill)$ exactly. From soundness requirement 3, $\varphi(in)$ is disjoint from $\varphi(kill)$. This implies that $\varphi(out - kill)$ is disjoint from $\varphi(kill)$, and so $\varphi(out - kill) = \varphi(out) - \varphi(kill)$. Then $\varphi(in) = (\varphi(out) - \varphi(kill)) \cup \varphi(gen) = (\varphi(out) - kill') \cup gen'$. We can conclude that $out' \subset \varphi(out) \implies in' \subset \varphi(in)$. 2. If the statement is removed. As $\varphi(statement)$ is a tautological assignment, we know that $\varphi(gen) = \varphi(kill) = \\{ destination \\}$, while $gen' = kill' = \emptyset$. So $\varphi(in) = \varphi(out) \cup \\{ destination \\}$. Then $in' = out' \subset out \subset \varphi(in)$. By recursion, we can conclude by that $in' \subset \varphi(in)$ everywhere. </details> This approximate liveness results is only suboptimal if there are locals that fully disappear from the CFG due to an assignment cycle. These cases are quite unlikely, so we do not bother with them. This change allows to reduce the perf impact of DestinationPropagation by half on diesel and ucd (https://github.com/rust-lang/rust/pull/115105#issuecomment-1694701904). cc ````@JakobDegen````
2024-01-17Auto merge of #120019 - lcnr:fn-wf, r=BoxyUwUbors-1/+34
fix fn/const items implied bounds and wf check (rebase) A rebase of #104098, see that PR for discussion. This is pretty much entirely the work of `@aliemjay.` I received his permission for this rebase. --- These are two distinct changes (edit: actually three, see below): 1. Wf-check all fn item args. This is a soundness fix. Fixes #104005 2. Use implied bounds from impl header in borrowck of associated functions/consts. This strictly accepts more code and helps to mitigate the impact of other breaking changes. Fixes #98852 Fixes #102611 The first is a breaking change and will likely have a big impact without the the second one. See the first commit for how it breaks libstd. Landing the second one without the first will allow more incorrect code to pass. For example an exploit of #104005 would be as simple as: ```rust use core::fmt::Display; trait ExtendLt<Witness> { fn extend(self) -> Box<dyn Display>; } impl<T: Display> ExtendLt<&'static T> for T { fn extend(self) -> Box<dyn Display> { Box::new(self) } } fn main() { let val = (&String::new()).extend(); println!("{val}"); } ``` The third change is to to check WF of user type annotations before normalizing them (fixes #104764, fixes #104763). It is mutually dependent on the second change above: an attempt to land it separately in #104746 caused several crater regressions that can all be mitigated by using the implied from the impl header. It is also necessary for the soundness of associated consts that use the implied bounds of impl header. See #104763 and how the third commit fixes the soundness issue in `tests/ui/wf/wf-associated-const.rs` that was introduces by the previous commit. r? types
2024-01-16Auto merge of #116520 - Enselic:large-copy-into-fn, r=oli-obkbors-12/+18
large_assignments: Lint on specific large args passed to functions Requires lowering function call arg spans down to MIR, which is done in the second commit. Part of #83518 Also see * https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/arg.20Spans.20for.20TerminatorKind.3A.3ACall.3F * https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/move_size_limit.20lint r? `@oli-obk` (E-mentor)
2024-01-16Rollup merge of #119969 - compiler-errors:simplify-closure-env-ty, r=oli-obkMatthias Krüger-1/+5
Simplify `closure_env_ty` and `closure_env_param` Random cleanup that I found when working on async closures. This makes it easier to separate the latter into a new tykind.
2024-01-16borrowck: use implied bounds from impl headerAli MJ Al-Nasrawy-1/+24
2024-01-16borrowck: wf-check fn item argsAli MJ Al-Nasrawy-0/+10
2024-01-15compiler: Lower fn call arg spans down to MIRMartin Nordholts-12/+18
To enable improved accuracy of diagnostics in upcoming commits.
2024-01-15Rollup merge of #119971 - compiler-errors:zip-eq, r=nnethercoteMatthias Krüger-3/+10
Use `zip_eq` to enforce that things being zipped have equal sizes Some `zip`s are best enforced to be equal, since size mismatches suggest deeper bugs in the compiler.
2024-01-15Rollup merge of #119897 - compiler-errors:fulfillment-errors, r=lcnrMatthias Krüger-2/+2
`OutputTypeParameterMismatch` -> `SignatureMismatch` I'm probably missing something that made this rename more complicated. What did you end up getting stuck on when renaming this selection error, `@lcnr?` **also** I renamed the `FulfillmentErrorCode` variants. This is just churn but I wanted to do it forever. I can move it out of this PR if desired. r? lcnr
2024-01-14Use zip_eq to enforce that things being zipped have equal sizesMichael Goulet-3/+10
2024-01-14Simplify closure_env_ty and closure_env_paramMichael Goulet-1/+5
2024-01-13Make InferCtxtExt::could_impl_trait less messed upMichael Goulet-13/+18
2024-01-12Remove redundant Code from FulfillmentErrorCode variantsMichael Goulet-2/+2
2024-01-11Stop using `DiagnosticBuilder::buffer` in `BorrowckErrors`.Nicholas Nethercote-9/+10
But we can't easily switch from `Vec<Diagnostic>` to `Vec<DiagnosticBuilder<G>>` because there's a mix of errors and warnings which result in different `G` types. So we must make `DiagnosticBuilder::into_diagnostic` public, but that's ok, and it will get more use in subsequent commits.
2024-01-11Rollup merge of #118915 - compiler-errors:alias-nits, r=lcnrMatthias Krüger-2/+2
Add some comments, add `can_define_opaque_ty` check to `try_normalize_ty_recur` Follow-up from #117278, since I was recently re-reviewing this code.
2024-01-10Simplify some redundant namesMichael Goulet-2/+2
2024-01-10Rename consuming chaining methods on `DiagnosticBuilder`.Nicholas Nethercote-19/+19
In #119606 I added them and used a `_mv` suffix, but that wasn't great. A `with_` prefix has three different existing uses. - Constructors, e.g. `Vec::with_capacity`. - Wrappers that provide an environment to execute some code, e.g. `with_session_globals`. - Consuming chaining methods, e.g. `Span::with_{lo,hi,ctxt}`. The third case is exactly what we want, so this commit changes `DiagnosticBuilder::foo_mv` to `DiagnosticBuilder::with_foo`. Thanks to @compiler-errors for the suggestion.
2024-01-10Add `DiagCtxt::delayed_bug`.Nicholas Nethercote-2/+2
We have `span_delayed_bug` and often pass it a `DUMMY_SP`. This commit adds `delayed_bug`, which matches pairs like `err`/`span_err` and `warn`/`span_warn`.
2024-01-10Rename `struct_span_err!` as `struct_span_code_err!`.Nicholas Nethercote-27/+46
Because it takes an error code after the span. This avoids the confusing overlap with the `DiagCtxt::struct_span_err` method, which doesn't take an error code.
2024-01-08Use chaining in `DiagnosticBuilder` construction.Nicholas Nethercote-67/+49
To avoid the use of a mutable local variable, and because it reads more nicely.
2024-01-08Make `DiagnosticBuilder::emit` consuming.Nicholas Nethercote-2/+2
This works for most of its call sites. This is nice, because `emit` very much makes sense as a consuming operation -- indeed, `DiagnosticBuilderState` exists to ensure no diagnostic is emitted twice, but it uses runtime checks. For the small number of call sites where a consuming emit doesn't work, the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will be removed in subsequent commits.) Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes consuming, while `delay_as_bug_without_consuming` is added (which will also be removed in subsequent commits.) All this requires significant changes to `DiagnosticBuilder`'s chaining methods. Currently `DiagnosticBuilder` method chaining uses a non-consuming `&mut self -> &mut Self` style, which allows chaining to be used when the chain ends in `emit()`, like so: ``` struct_err(msg).span(span).emit(); ``` But it doesn't work when producing a `DiagnosticBuilder` value, requiring this: ``` let mut err = self.struct_err(msg); err.span(span); err ``` This style of chaining won't work with consuming `emit` though. For that, we need to use to a `self -> Self` style. That also would allow `DiagnosticBuilder` production to be chained, e.g.: ``` self.struct_err(msg).span(span) ``` However, removing the `&mut self -> &mut Self` style would require that individual modifications of a `DiagnosticBuilder` go from this: ``` err.span(span); ``` to this: ``` err = err.span(span); ``` There are *many* such places. I have a high tolerance for tedious refactorings, but even I gave up after a long time trying to convert them all. Instead, this commit has it both ways: the existing `&mut self -> Self` chaining methods are kept, and new `self -> Self` chaining methods are added, all of which have a `_mv` suffix (short for "move"). Changes to the existing `forward!` macro lets this happen with very little additional boilerplate code. I chose to add the suffix to the new chaining methods rather than the existing ones, because the number of changes required is much smaller that way. This doubled chainging is a bit clumsy, but I think it is worthwhile because it allows a *lot* of good things to subsequently happen. In this commit, there are many `mut` qualifiers removed in places where diagnostics are emitted without being modified. In subsequent commits: - chaining can be used more, making the code more concise; - more use of chaining also permits the removal of redundant diagnostic APIs like `struct_err_with_code`, which can be replaced easily with `struct_err` + `code_mv`; - `emit_without_diagnostic` can be removed, which simplifies a lot of machinery, removing the need for `DiagnosticBuilderState`.
2024-01-07Move PointIndex to mir_dataflow.Camille GILLOT-114/+32
2024-01-05Rollup merge of #119563 - compiler-errors:coroutine-resume, r=oli-obkMatthias Krüger-26/+46
Check yield terminator's resume type in borrowck In borrowck, we didn't check that the lifetimes of the `TerminatorKind::Yield`'s `resume_place` were actually compatible with the coroutine's signature. That means that the lifetimes were totally going unchecked. Whoops! This PR implements this checking. Fixes #119564 r? types
2024-01-05Remove `hir::Guard`Matthew Jasper-1/+1
Use Expr instead. Use `ExprKind::Let` to represent if let guards.
2024-01-04Check yield terminator's resume type in borrowckMichael Goulet-26/+46
2023-12-30is_coroutine -> is_coroutine_or_closureMichael Goulet-3/+3
2023-12-28Movability doesn't need to be a query anymoreMichael Goulet-1/+1
2023-12-28Remove movability from TyKind::CoroutineMichael Goulet-26/+23
2023-12-28Fix some commentscuishuang-1/+1
Signed-off-by: cuishuang <imcusg@gmail.com>
2023-12-26Auto merge of #119258 - compiler-errors:closure-kind, r=eholkbors-102/+149
Make closures carry their own ClosureKind Right now, we use the "`movability`" field of `hir::Closure` to distinguish a closure and a coroutine. This is paired together with the `CoroutineKind`, which is located not in the `hir::Closure`, but the `hir::Body`. This is strange and redundant. This PR introduces `ClosureKind` with two variants -- `Closure` and `Coroutine`, which is put into `hir::Closure`. The `CoroutineKind` is thus removed from `hir::Body`, and `Option<Movability>` no longer needs to be a stand-in for "is this a closure or a coroutine". r? eholk
2023-12-25Flatten matchMichael Goulet-47/+67
2023-12-25Only regular coroutines have movabilityMichael Goulet-28/+28