about summary refs log tree commit diff
path: root/compiler/rustc_borrowck/src
AgeCommit message (Collapse)AuthorLines
2025-09-12Introduce trait_item_ofCameron Steffen-1/+1
2025-09-09erase_regions to erase_and_anonymize_regionsBoxy-5/+7
2025-09-06identity uses are ok, even if there are no defining useslcnr-1/+10
2025-09-01Auto merge of #145925 - lcnr:revealing-use-closures-2, r=BoxyUwUbors-201/+456
`-Znext-solver`: support non-defining uses in closures Cleaned up version of rust-lang/rust#139587, finishing the implementation of https://github.com/rust-lang/types-team/issues/129. This does not affect stable. The reasoning for why this is the case is subtle however. ## What does it do We split `do_mir_borrowck` into `borrowck_collect_region_constraints` and `borrowck_check_region_constraints`, where `borrowck_collect_region_constraints` returns an enormous `CollectRegionConstraintsResult` struct which contains all the relevant data to actually handle opaque type uses and to check the region constraints later on. `query mir_borrowck` now simply calls `BorrowCheckRootCtxt::do_mir_borrowck` which starts by iterating over all nested bodies of the current function - visiting nested bodies before their parents - and computing their `CollectRegionConstraintsResult`. After we've collected all constraints it's time to actually compute the concrete types for the opaques defined by this function. With this PR we now compute the concrete types of opaques for each body before using them to check the non-defining uses of any of them. After we've computed the concrete types by using all bodies, we use `apply_computed_concrete_opaque_types` for each body to constrain non-defining uses, before finally finishing with `borrowck_check_region_constraints`. We always visit nested bodies before their parents when doing this. ## `ClosureRegionRequirements` As we only call `borrowck_collect_region_constraints` for nested bodies before type checking the parent, we can't simply use the final `ClosureRegionRequirements` of the nested body during MIR type check. We instead track that we need to apply these requirements in `deferred_closure_requirements`. We now manually apply the final closure requirements to each body after handling opaque types. This works, except that we may need the region constraints of nested bodies to successfully define an opaque type in the parent. This is handled by using a new `fn compute_closure_requirements_modulo_opaques` which duplicates region checking - while ignoring any errors - before we've added the constraints from `apply_computed_concrete_opaque_types`. This is necessary for a lot of async tests, as pretty much the entire function is inside of an async block while the opaque type gets defined in the parent. As an performance optimization we only use `fn compute_closure_requirements_modulo_opaques` in case the nested body actually depends on any opaque types. Otherwise we eagerly call `borrowck_check_region_constraints` and apply the final closure region requirements right away. ## Impact on stable code Handling the opaque type uses in the parent function now only uses the closure requirements *modulo opaques*, while it previously also considered member constraints from nested bodies. `External` regions are never valid choice regions. Also, member constraints will never constrain a member region if it is required to be outlived by an external region, as that fails the upper-bound check. https://github.com/rust-lang/rust/blob/564ee219127b796d56f74767366fd359758b97de/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs#L90-L96 Member constraints therefore never add constraints for external regions :> r? `@BoxyUwU`
2025-09-01use defining uses of all bodies to constrain non-defining useslcnr-201/+456
support non-defining uses in closures
2025-09-01Introduce `MirDumper` and `MirWriter`.Nicholas Nethercote-74/+48
MIR dumping is a mess. There are lots of functions and entry points, e.g. `dump_mir`, `dump_mir_with_options`, `dump_polonius_mir`, `dump_mir_to_writer`. Also, it's crucial that `create_dump_file` is never called without `dump_enabled` first being checked, but there is no mechanism for ensuring this and it's hard to tell if it is satisfied on all paths. (`dump_enabled` is checked twice on some paths, however!) This commit introduces `MirWriter`, which controls the MIR writing, and encapsulates the `extra_data` closure and `options`. Two existing functions are now methods of this type. It sets reasonable defaults, allowing the removal of many `|_, _| Ok(())` closures. The commit also introduces `MirDumper`, which is layered on top of `MirWriter`, and which manages the creation of the dump files, encapsulating pass names, disambiguators, etc. Four existing functions are now methods of this type. - `MirDumper::new` will only succeed if dumps are enabled, and will return `None` otherwise, which makes it impossible to dump when you shouldn't. - It also sets reasonable defaults for various things like disambiguators, which means you no longer need to specify them in many cases. When they do need to be specified, it's now done via setter methods. - It avoids some repetition. E.g. `dump_nll_mir` previously specifed the pass name `"nll"` four times and the disambiguator `&0` three times; now it specifies them just once, to put them in the `MirDumper`. - For Polonius, the `extra_data` closure can now be specified earlier, which avoids having to pass some arguments through some functions.
2025-09-01Use trait object references for closures.Nicholas Nethercote-3/+3
The dynamic dispatch cost doesn't matter for MIR dumping, which is perf-insensitive. And it's necessary for the next commit, which will store some `extra_data` closures in a struct.
2025-08-27Auto merge of #140737 - amandasystems:revised-constraint-search, r=lcnrbors-202/+247
Region inference: Use outlives-static constraints in constraint search Revise the extra `r: 'static` constraints added upon universe issues to add an explanation, and use that explanation during constraint blame search. This greatly simplifies the region inference logic, which now does not need to reverse-engineer the event that caused a region to outlive `'static`. This cosmetically changes the output of two UI tests. I blessed them i separate commits with separate motivations, but that can of course be squashed as desired. We probably want that. The PR was extracted out of rust-lang/rust#130227 and consists of one-third of its functional payload. r? lcnr
2025-08-25Auto merge of #145711 - lcnr:non-defining-uses-hir-typeck, r=BoxyUwUbors-10/+9
Support non-defining uses in HIR typeck This changes the impl of `NormalizesTo` for opaque types to be structural during HIR typeck. The previous impl equated region variables of the opaque type key with existing entries which can result in spurious leak check errors and also results in mismatches with MIR borrowck, theoretically causing ICE. The approach is very similar to rust-lang/rust#145244 in MIR typeck: - we collect all uses of opaque types during HIR typeck - before writeback, we search for *defining uses* - the opaque type key has fully universal generic args modulo regions - the hidden type has no infer vars - we use these defining uses to compute the concrete type for the opaque and map it to the definition site - we use this concrete type to check the type of all uses of opaques during HIR typeck. This also constrains infer vars in non-defining uses Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/135, fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/49. r? `@BoxyUwU`
2025-08-25change non-defining use error messagelcnr-1/+0
2025-08-25support non-defining uses in HIR typecklcnr-10/+10
2025-08-25Rollup merge of #145620 - compiler-errors:fake-dyn-to-dyn, r=lcnrStuart Cook-62/+74
Account for impossible bounds making seemingly unsatisfyable dyn-to-dyn casts Fixes https://github.com/rust-lang/rust/issues/141806 When we have an impossible where clause like `dyn Trait<u8>: Sized`, this may make a dyn-to-dyn cast like `dyn Trait<()> -> dyn trait<u8>` to successfully type check as if it were a wide-to-thin ptr cast (discarding metadata): https://github.com/rust-lang/rust/blob/16ad385579cebb6f7d53367c552661b6b51a4a02/compiler/rustc_hir_typeck/src/cast.rs#L862-L865 In borrowck, we are expecting that the only meaningful dyn-to-dyn cast to be a metadata-preserving wide-to-wide ptr cast, which requires that the principals of the dyn pointers are equal. Borrowck additionally assumes that these principals have already been proven equal *modulo regions*, and we thus ICE since `Trait<u8>` and `Trait<()>` do not unify: https://github.com/rust-lang/rust/blob/16ad385579cebb6f7d53367c552661b6b51a4a02/compiler/rustc_borrowck/src/type_check/mod.rs#L1481-L1524 This PR fixes this ICE by checking whether the RHS of the cast is considered to be Sized in the environment of the MIR typeck, and if so then skipping over this dyn->dyn principal compatibility check. r? `@lcnr` perhaps?
2025-08-23Simplify SCC annotations somewhatAmanda Stjerna-24/+8
2025-08-23NitsMichael Goulet-71/+72
2025-08-23Account for impossible bounds making seemingly unsatisfyable dyn-to-dyn castsMichael Goulet-11/+22
2025-08-22change HIR typeck unification handling approachlcnr-45/+51
2025-08-22Region inference: Use outlives-static constraints in constraint searchAmanda Stjerna-188/+249
Revise the extra `r: 'static` constraints added upon universe issues to add an explanation, and use that explanation during constraint blame search. This greatly simplifies the region inference logic, which now does not need to reverse-engineer the event that caused a region to outlive 'static.
2025-08-21Auto merge of #145701 - jhpratt:rollup-a0kg33p, r=jhprattbors-1/+1
Rollup of 19 pull requests Successful merges: - rust-lang/rust#143383 (stabilize `const_array_each_ref`) - rust-lang/rust#144758 ([Doc] Add links to the various collections) - rust-lang/rust#144915 (Defer tail call ret ty equality to check_tail_calls) - rust-lang/rust#145256 (Add new `--test-codegen-backend` bootstrap option) - rust-lang/rust#145297 (fix(debuginfo): handle false positives in overflow check) - rust-lang/rust#145390 (Shorten some dependency chains in the compiler) - rust-lang/rust#145415 (std_detect: RISC-V: implement implication to "C") - rust-lang/rust#145525 (stdlib: Replace typedef -> type alias in doc comment) - rust-lang/rust#145590 (Prevent impossible combinations in `ast::ModKind`.) - rust-lang/rust#145593 (UnsafePinned::raw_get: sync signature with get) - rust-lang/rust#145621 (Fix some doc typos) - rust-lang/rust#145627 (Unconditionally-const supertraits are considered not dyn compatible) - rust-lang/rust#145642 (Do not use effective_visibilities query for Adt types of a local trait while proving a where-clause) - rust-lang/rust#145650 (Fix JS search scripts path) - rust-lang/rust#145654 (Download CI GCC into the correct directory) - rust-lang/rust#145662 (Enforce correct number of arguments for `"x86-interrupt"` functions) - rust-lang/rust#145673 (Add flock support for cygwin) - rust-lang/rust#145674 (Enable triagebot `[review-changes-since]` feature) - rust-lang/rust#145678 (Fix typo in docstring) r? `@ghost` `@rustbot` modify labels: rollup
2025-08-20diagnostics :3lcnr-19/+43
2025-08-20handle opaque types before region inferencelcnr-1128/+957
2025-08-20`region_infer::opaque_types` to folderlcnr-0/+0
2025-08-20`fully_perform_op_raw` out of `TypeChecker`lcnr-31/+75
2025-08-19Defer tail call ret ty equality to check_tail_callsMichael Goulet-1/+1
2025-08-19Rollup merge of #142079 - lcnr:opaque-types-universes, r=BoxyUwU许杰友 Jieyou Xu (Joe)-2/+7
nll-relate: improve hr opaque types support This should currently not be user-facing outside of diagnostics as even if we successfully relate the opaque types, we don't support opaque types with non-param arguments and also require all member regions to be equal to the arguments or `'static`. This means there's no way to end up with a placeholder in the hidden type. r? types
2025-08-19Rollup merge of #145041 - lcnr:borrowck-limitations-error, r=BoxyUwUStuart Cook-13/+72
rework GAT borrowck limitation error The old one depends on the `ConstraintCategory` of the constraint which meant we did not emit this note if we had to prove the higher ranked trait bound due to e.g. normalization. This made it annoying brittle and caused MIR borrowck errors to be order dependent, fixes the issue in https://github.com/rust-lang/rust/pull/140737#discussion_r2259592651. r? types cc ```@amandasystems```
2025-08-18comment style changesDeadbeef-35/+34
2025-08-18nll-relate: improve hr opaque types supportlcnr-2/+7
2025-08-17refactor return type of `suggest_ampmut` into an enumDeadbeef-171/+178
2025-08-16overhaul `&mut` suggestions in borrowck errorsDeadbeef-323/+360
2025-08-15Auto merge of #142071 - lcnr:revealing-use, r=compiler-errorsbors-1/+12
`apply_member_constraints`: fix placeholder check Checking whether the member region is *an existential region from a higher universe* is just wrong and I am pretty sure we've added that check by accident as the naming was just horribly confusing before rust-lang/rust#140466. I've encountered this issue separately while working on rust-lang/rust#139587, but feel like it's probably easier to separately FCP this change. This allows the following code to compile ```rust trait Proj<'a> { type Assoc; } impl<'a, 'b, F: FnOnce() -> &'b ()> Proj<'a> for F { type Assoc = (); } fn is_proj<F: for<'a> Proj<'a>>(f: F) {} fn define<'a>() -> impl Sized + use<'a> { // This adds a use of `opaque::<'a>` with hidden type `&'unconstrained_b ()`. // 'unconstrained_b is an inference variable from a higher universe as it gets // created inside of the binder of `F: for<'a> Proj<'a>`. This previously // caused us to not apply member constraints. We now do, constraining // it to `'a`. is_proj(define::<'a>); &() } fn main() {} ``` This should not be breaking change, even in theory. Applying member constraints is incomplete in rare circumstances which means that applying them in more cases can cause spurious errors, cc rust-lang/rust#140569/rust-lang/rust#142073. However, as we always skipped these member regions in `apply_member_constraints` the skipped region is guaranteed to cause an error in `check_member_constraints` later on.
2025-08-14Adjust error message grammar to be less awkwardJake Goulding-1/+1
2025-08-14add commentlcnr-1/+6
2025-08-13Cleanup assoc parent utilsCameron Steffen-5/+3
2025-08-13rework `add_placeholder_from_predicate_note`lcnr-9/+49
2025-08-13also consider HR boundslcnr-3/+17
2025-08-13avoid duplicate error stringlcnr-1/+1
2025-08-11Rollup merge of #145111 - fee1-dead-contrib:push-rlvnyrztlkpq, r=jieyouxuGuillaume Gomez-16/+0
remove some unused private trait impls they're neither required for completeness nor used
2025-08-11remove `from_forall`lcnr-18/+15
2025-08-10review commentsEsteban Küber-5/+7
2025-08-10Add support for method callsEsteban Küber-33/+41
2025-08-10Point at the `Fn()` or `FnMut()` bound that coerced a closure, which caused ↵Esteban Küber-1/+39
a move error When encountering a move error involving a closure because the captured value isn't `Copy`, and the obligation comes from a bound on a type parameter that requires `Fn` or `FnMut`, we point at it and explain that an `FnOnce` wouldn't cause the move error. ``` error[E0507]: cannot move out of `foo`, a captured variable in an `Fn` closure --> f111.rs:15:25 | 14 | fn do_stuff(foo: Option<Foo>) { | --- ----------- move occurs because `foo` has type `Option<Foo>`, which does not implement the `Copy` trait | | | captured outer variable 15 | require_fn_trait(|| async { | -- ^^^^^ `foo` is moved here | | | captured by this `Fn` closure 16 | if foo.map_or(false, |f| f.foo()) { | --- variable moved due to use in coroutine | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once --> f111.rs:12:53 | 12 | fn require_fn_trait<F: Future<Output = ()>>(_: impl Fn() -> F) {} | ^^^^^^^^^ help: consider cloning the value if the performance cost is acceptable | 16 | if foo.clone().map_or(false, |f| f.foo()) { | ++++++++ ```
2025-08-10Rollup merge of #145191 - dianne:fix-borrow-suggestion-args, r=compiler-errorsStuart Cook-7/+22
`suggest_borrow_generic_arg`: use the correct generic args The suggestion now gets calls' generic arguments from the callee's type to handle cases where the callee isn't an identifier expression. Fixes rust-lang/rust#145164.
2025-08-10Rollup merge of #143093 - lqd:polonius-pre-alpha, r=jackh726Stuart Cook-201/+31
Simplify polonius location-sensitive analysis This PR reworks the location-sensitive analysis into what we think is a worthwhile subset of the datalog analysis. A sort of polonius alpha analysis that handles NLL problem case 3 and more, but is still using the faster "reachability as an approximation of liveness", as well as the same loans-in-scope computation as NLLs -- and thus doesn't handle full flow-sensitivity like the datalog implementation. In the last few months, we've identified this subset as being actionable: - we believe we can make a stabilizable version of this analysis - it is an improvement over the status quo - it can also be modeled in a-mir-formality, or some other formalism, for assurances about soundness, and I believe ````````@nikomatsakis```````` is interested in looking into this during H2. - and we've identified the areas of work we wish to explore later to gradually expand the supported cases: the differences between reachability and liveness, support of kills, and considerations of time-traveling, for example. The approach in this PR is to try less to have the graph only represent live paths, by checking whether we reach a live region during traversal and recording the loan as live there, instead of equating traversal with liveness like today because it has subtleties with the typeck edges in statements (that could forward loans to the successor point without ensuring their liveness). We can then also simplify these typeck stmt edges. And we also can simplify traversal by removing looking at kills, because that's enough to handle a bunch of NLL problem 3 cases -- and we can gradually support them more and more in traversal in the future, to reduce the approximation of liveness. There's still some in-progress pieces of work w/r/t opaque types that I'm expecting [lcnr's opaque types rework](https://github.com/rust-lang/rust/pull/139587), and [amanda's SCCs rework](https://github.com/rust-lang/rust/pull/130227) to handle. That didn't seem to show up in tests until I rebased today (and shows lack of test coverage once again) when https://github.com/rust-lang/rust/pull/142255 introduced a couple of test failures with the new captures rules from edition 2024. It's not unexpected since we know more work is needed with member constraints (and we're not even using SCCs in this prototype yet) I'll look into these anyways, both for future work, and checking how these other 2 PRs would change things. --- I'm not sure the following means a lot until we have some formalism in-place, but: - I've changed the polonius compare-mode to use this analysis: the tests pass with it, except 2 cases with minor diagnostics differences, and the 2 edition 2024 opaque types one I mentioned above and need to investigate - things that are expected to work still do work: it bootstraps, can run our rustc-perf benchmarks (and the results are not even that bad), and a crater run didn't find any regressions (forgetting that crater currently fails to test around a quarter of all crates 👼) - I've added tests with improvements, like the NLL problem case 3 and others, as well as some that behave the same as NLLs today and are thus worse than the datalog implementation r? ````````@jackh726```````` (no rush I know you're deep in phd work and "implmentating" the new trait solver for r-a :p <3) This also fixes rust-lang/rust#135646, a diagnostics ICE from the previous implementation.
2025-08-09`suggest_borrow_generic_arg`: use the correct generic argsdianne-7/+22
2025-08-09Rollup merge of #145115 - lcnr:less-borrowck-tainting, r=compiler-errorsStuart Cook-64/+87
defer opaque type errors, generally greatly reduce tainting fixes the test for rust-lang/rust#135528, does not actually fix that issue properly. This is useful as it causes the migration to rust-lang/rust#139587 to be a lot easier.
2025-08-09Rollup merge of #144988 - amandasystems:more-detailed-region-graph, r=lcnrStuart Cook-6/+21
Add annotations to the graphviz region graph on region origins This adds - `(ex<'e>)` for regions whose origin is existential, with name if one exists, - `(for<'p>)` for regions whose origin is a placeholder, with name if one exists For any region whose name we don't know, use `'_`. This has helped _my_ debugging and it doesn't create too bad clutter, I feel. The change ~~is~~was ridiculously small, but I turned it into a separate PR so we can bikeshed the format. The following snippet: ```rust struct Co<'a>(&'a ()); struct Contra<'a>(fn(&'a ())); // `exists<'e> forall<'p> 'p: 'e` -> ERROR fn p_outlives_e( x: for<'e> fn(for<'p> fn(fn(fn(Contra<'e>, Co<'p>)))), ) -> fn(fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) { x ``` Gives this graph: ![new-naming](https://github.com/user-attachments/assets/f2c8f17c-d29b-4d42-9da7-4b8e520e76a6)
2025-08-08borrowck: defer opaque type errorslcnr-47/+70
2025-08-08borrowck: move error tainting earlierlcnr-17/+17
2025-08-09remove some unused private trait implsDeadbeef-16/+0
2025-08-08turn expensive assert into debug assertionRémy Rakic-2/+3