about summary refs log tree commit diff
path: root/compiler
AgeCommit message (Collapse)AuthorLines
2024-03-19Auto merge of #122392 - BoxyUwU:misc_cleanup, r=lcnrbors-24/+37
misc cleanups from debugging something rename `instantiate_canonical_with_fresh_inference_vars` to `instantiate_canonical` the substs for the canonical are not solely infer vars as that would be wildly wrong and it is rather confusing to see this method called and think that the entire canonicalization setup is completely broken when it is not :thumbsup: also update region debug printing to be more like the custom impls for Ty/Const, right now regions in debug output are horribly verbose and make it incredibly hard to read but with this atleast boundvars and placeholders when debugging the new solver do not take up excessive amounts of space. r? `@lcnr`
2024-03-19Auto merge of #122037 - oli-obk:more_new_intrinsics, r=Nilstriebbors-50/+28
Move more intrinsics to rustc_intrinsic cc https://github.com/rust-lang/rust/issues/63585
2024-03-19Auto merge of #122021 - oli-obk:delangitemification, r=compiler-errorsbors-183/+51
Use hir::Node helper methods instead of repeating the same impl multiple times I wanted to do something entirely different and stumbled upon a bunch of cleanups
2024-03-19Remove all checks of `IntrinsicDef::must_be_overridden` except for the ↵Oli Scherer-32/+11
actual overrides in codegen
2024-03-19Make span_bug panic site useful againOli Scherer-9/+18
2024-03-19Make ptr_guaranteed_cmp a rustc_intrinsic and favor its body over backends ↵Oli Scherer-15/+1
implementing it
2024-03-19Make `const_eval_select` a rustc_intrinsicOli Scherer-4/+8
2024-03-19Auto merge of #119212 - w-utter:pretty-print-const-expr, r=compiler-errorsbors-2/+152
Fix representation when printing abstract consts Previously, when printing a const generic expr, it would only display it as `{{const expr}}`. This allows for a more legible representation when printing these out. I also zipped the types with their constants for abstract consts that contain function calls when using type annotations, eg: `foo(S: usize, true: bool) -> usize` insteaad of `foo(S, true): fn(usize, bool) -> usize` for conciseness.
2024-03-19Auto merge of #122493 - lukas-code:sized-constraint, r=lcnrbors-115/+122
clean up `Sized` checking This PR cleans up `sized_constraint` and related functions to make them simpler and faster. This should not make more or less code compile, but it can change error output in some rare cases. ## enums and unions are `Sized`, even if they are not WF The previous code has some special handling for enums, which made them sized if and only if the last field of each variant is sized. For example given this definition (which is not WF) ```rust enum E<T1: ?Sized, T2: ?Sized, U1: ?Sized, U2: ?Sized> { A(T1, T2), B(U1, U2), } ``` the enum was sized if and only if `T2` and `U2` are sized, while `T1` and `T2` were ignored for `Sized` checking. After this PR this enum will always be sized. Unsized enums are not a thing in Rust and removing this special case allows us to return an `Option<Ty>` from `sized_constraint`, rather than a `List<Ty>`. Similarly, the old code made an union defined like this ```rust union Union<T: ?Sized, U: ?Sized> { head: T, tail: U, } ``` sized if and only if `U` is sized, completely ignoring `T`. This just makes no sense at all and now this union is always sized. ## apply the "perf hack" to all (non-error) types, instead of just type parameters This "perf hack" skips evaluating `sized_constraint(adt): Sized` if `sized_constraint(adt): Sized` exactly matches a predicate defined on `adt`, for example: ```rust // `Foo<T>: Sized` iff `T: Sized`, but we know `T: Sized` from a predicate of `Foo` struct Foo<T /*: Sized */>(T); ``` Previously this was only applied to type parameters and now it is applied to every type. This means that for example this type is now always sized: ```rust // Note that this definition is WF, but the type `S<T>` not WF in the global/empty ParamEnv struct S<T>([T]) where [T]: Sized; ``` I don't anticipate this to affect compile time of any real-world program, but it makes the code a bit nicer and it also makes error messages a bit more consistent if someone does write such a cursed type. ## tuples are sized if the last type is sized The old solver already has this behavior and this PR also implements it for the new solver and `is_trivially_sized`. This makes it so that tuples work more like a struct defined like this: ```rust struct TupleN<T1, T2, /* ... */ Tn: ?Sized>(T1, T2, /* ... */ Tn); ``` This might improve the compile time of programs with large tuples a little, but is mostly also a consistency fix. ## `is_trivially_sized` for more types This function is used post-typeck code (borrowck, const eval, codegen) to skip evaluating `T: Sized` in some cases. It will now return `true` in more cases, most notably `UnsafeCell<T>` and `ManuallyDrop<T>` where `T.is_trivially_sized`. I'm anticipating that this change will improve compile time for some real world programs.
2024-03-19Auto merge of #122055 - compiler-errors:stabilize-atb, r=oli-obkbors-28/+13
Stabilize associated type bounds (RFC 2289) This PR stabilizes associated type bounds, which were laid out in [RFC 2289]. This gives us a shorthand to express nested type bounds that would otherwise need to be expressed with nested `impl Trait` or broken into several `where` clauses. ### What are we stabilizing? We're stabilizing the associated item bounds syntax, which allows us to put bounds in associated type position within other bounds, i.e. `T: Trait<Assoc: Bounds...>`. See [RFC 2289] for motivation. In all position, the associated type bound syntax expands into a set of two (or more) bounds, and never anything else (see "How does this differ[...]" section for more info). Associated type bounds are stabilized in four positions: * **`where` clauses (and APIT)** - This is equivalent to breaking up the bound into two (or more) `where` clauses. For example, `where T: Trait<Assoc: Bound>` is equivalent to `where T: Trait, <T as Trait>::Assoc: Bound`. * **Supertraits** - Similar to above, `trait CopyIterator: Iterator<Item: Copy> {}`. This is almost equivalent to breaking up the bound into two (or more) `where` clauses; however, the bound on the associated item is implied whenever the trait is used. See #112573/#112629. * **Associated type item bounds** - This allows constraining the *nested* rigid projections that are associated with a trait's associated types. e.g. `trait Trait { type Assoc: Trait2<Assoc2: Copy>; }`. * **opaque item bounds (RPIT, TAIT)** - This allows constraining associated types that are associated with the opaque without having to *name* the opaque. For example, `impl Iterator<Item: Copy>` defines an iterator whose item is `Copy` without having to actually name that item bound. The latter three are not expressible in surface Rust (though for associated type item bounds, this will change in #120752, which I don't believe should block this PR), so this does represent a slight expansion of what can be expressed in trait bounds. ### How does this differ from the RFC? Compared to the RFC, the current implementation *always* desugars associated type bounds to sets of `ty::Clause`s internally. Specifically, it does *not* introduce a position-dependent desugaring as laid out in [RFC 2289], and in particular: * It does *not* desugar to anonymous associated items in associated type item bounds. * It does *not* desugar to nested RPITs in RPIT bounds, nor nested TAITs in TAIT bounds. This position-dependent desugaring laid out in the RFC existed simply to side-step limitations of the trait solver, which have mostly been fixed in #120584. The desugaring laid out in the RFC also added unnecessary complication to the design of the feature, and introduces its own limitations to, for example: * Conditionally lowering to nested `impl Trait` in certain positions such as RPIT and TAIT means that we inherit the limitations of RPIT/TAIT, namely lack of support for higher-ranked opaque inference. See this code example: https://github.com/rust-lang/rust/pull/120752#issuecomment-1979412531. * Introducing anonymous associated types makes traits no longer object safe, since anonymous associated types are not nameable, and all associated types must be named in `dyn` types. This last point motivates why this PR is *not* stabilizing support for associated type bounds in `dyn` types, e.g, `dyn Assoc<Item: Bound>`. Why? Because `dyn` types need to have *concrete* types for all associated items, this would necessitate a distinct lowering for associated type bounds, which seems both complicated and unnecessary compared to just requiring the user to write `impl Trait` themselves. See #120719. ### Implementation history: Limited to the significant behavioral changes and fixes and relevant PRs, ping me if I left something out-- * #57428 * #108063 * #110512 * #112629 * #120719 * #120584 Closes #52662 [RFC 2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html
2024-03-18address nitsLukas Markeffsky-17/+18
2024-03-18Rollup merge of #122701 - compiler-errors:allocator-suspend, r=oli-obkMatthias Krüger-4/+10
Detect allocator for box in `must_not_suspend` lint I don't expect this to happen in practice, but better to check than not. Fixes #122643
2024-03-18Rollup merge of #122687 - lcnr:normalizes-to-emit-nested-goals, ↵Matthias Krüger-178/+222
r=compiler-errors `NormalizesTo`: return nested goals to caller Fixes the regression of `paperclip-core`. see https://hackmd.io/IsVAafiOTAaPIFcUxRJufw for more details. r? ```@compiler-errors```
2024-03-18Rollup merge of #122158 - estebank:feature-sugg, r=WaffleLapkinMatthias Krüger-40/+108
Provide structured suggestion for `#![feature(foo)]` ``` error: `S2<'_>` is forbidden as the type of a const generic parameter --> $DIR/lifetime-in-const-param.rs:5:23 | LL | struct S<'a, const N: S2>(&'a ()); | ^^ | = note: the only supported types are integers, `bool` and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] | ``` Fix #55941.
2024-03-18Rollup merge of #122060 - clubby789:stabilize-imported-main, r=lcnrMatthias Krüger-13/+2
Stabilize `imported_main` FCP: https://github.com/rust-lang/rust/issues/28937#issuecomment-1977822831 Docs: https://github.com/rust-lang/reference/pull/1461
2024-03-18Rollup merge of #121823 - Nadrieril:never-witnesses, r=compiler-errorsMatthias Krüger-47/+94
never patterns: suggest `!` patterns on non-exhaustive matches When a match is non-exhaustive we now suggest never patterns whenever it makes sense. r? ``@compiler-errors``
2024-03-18Rollup merge of #121258 - fmease:assoc-const-eq-reject-overly-generic-tys, ↵Matthias Krüger-11/+233
r=compiler-errors Reject overly generic assoc const binding types Split off from #119385 to make #119385 easier to review. --- In the *instantiated* type of assoc const bindings 1. reject **early-bound generic params** * Provide a rich error message instead of ICE'ing ([#108271](https://github.com/rust-lang/rust/issues/108271)). * This is a temporary and semi-artificial restriction until the arrival of *generic const generics*. * It's quite possible that rustc could already perfectly support this subset of generic const generics if we just removed some checks (some `.no_bound_vars().expect(…)`) but even if that was the case, I'd rather gate it behind a new feature flag. Reporting an error instead of ICE'ing is a good first step towards an eventual feature gate error. 2. reject **escaping late-bound generic params** * They lead to ICEs before & I'm pretty sure that they remain incorrect even in a world with *generic const generics* --- Together with #118668 & #119385, this supersedes #118360. Fixes #108271.
2024-03-18Use `hir::Node` helper methods instead of repeat the same impl multiple timesOli Scherer-119/+22
There already were inconsistencies, so this ensures we don't introduce subtle surprising bugs
2024-03-18Deduplicate `associated_body` and `body_id`Oli Scherer-64/+29
They match on almost the same patterns, which is fishy. Also turn `associated_body` into a method and do some cleanups nearby the call sites
2024-03-18Detect allocator for box in must_not_suspend lintMichael Goulet-4/+10
2024-03-18cleanup + reviewlcnr-35/+31
2024-03-18improve commentslcnr-7/+8
2024-03-18rename `instantiate_canonical_with_fresh_inference_vars`Boxy-16/+11
2024-03-18update region debug formattingBoxy-8/+26
2024-03-18Provide structured suggestion for `#![feature(foo)]`Esteban Küber-40/+108
``` error: `S2<'_>` is forbidden as the type of a const generic parameter --> $DIR/lifetime-in-const-param.rs:5:23 | LL | struct S<'a, const N: S2>(&'a ()); | ^^ | = note: the only supported types are integers, `bool` and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] | ``` Fix #55941.
2024-03-18Rollup merge of #122689 - Jarcho:missing_try, r=compiler-errorsMatthias Krüger-3/+3
Add missing `try_visit` calls in visitors.
2024-03-18Rollup merge of #122680 - lqd:nested-await-args, r=compiler-errorsMatthias Krüger-2/+1
Do not eat nested expressions' results in `MayContainYieldPoint` format args visitor #121563 unintentionally changed the `MayContainYieldPoint` format args visitor behavior, now missing yield points in nested expressions, as seen in #122674. The walk can find a yield point in an expression but it was ignored. r? ``@petrochenkov`` as the reviewer of #121563 cc ``@Jarcho`` as the author Fixes #122674. We're in the 1.77 release week. #121563 will land on 1.78 but beta is still 1.77.9: this PR will likely need to be backported soon after beta is cut.
2024-03-18Rollup merge of #122649 - cuviper:min-llvm-17, r=nikicMatthias Krüger-63/+4
Update the minimum external LLVM to 17 With this change, we'll have stable support for LLVM 17 and 18. For reference, the previous increase to LLVM 16 was #117947.
2024-03-18Rollup merge of #122647 - RalfJung:box-to-raw-retag, r=oli-obkMatthias Krüger-15/+34
add_retag: ensure box-to-raw-ptr casts are preserved for Miri In https://github.com/rust-lang/rust/pull/122233 I added `retag_box_to_raw` not realizing that we can already do `addr_of_mut!(*bx)` to turn a box into a raw pointer without an intermediate reference. We just need to ensure this information is preserved past the ElaborateBoxDerefs pass. r? ``@oli-obk``
2024-03-18Rollup merge of #122588 - klensy:imported_source_file, r=michaelwoeristerMatthias Krüger-10/+10
less useless filter calls in imported_source_file This reduces calls to `filter` greatly, giving 0.3% instructions win on some tests.
2024-03-18Rollup merge of #122567 - erikdesjardins:noname, r=oli-obkMatthias Krüger-1/+0
Remove fixme about LLVM basic block naming ~This may be a small perf win.~ Originally, this PR implemented the fixme, but it didn't have any measurable perf improvement. r? ``@ghost``
2024-03-18Add missing `try_visit` calls in visitors.Jason Newcomb-3/+3
2024-03-18`NormalizesTo` return nested goalslcnr-74/+128
2024-03-18move `normalizes_to_hack` to `AliasRelate`lcnr-67/+60
2024-03-18Avoid various uses of `Option<Span>` in favor of using `DUMMY_SP` in the few ↵Oli Scherer-66/+61
cases that used `None`
2024-03-18remove retag_box_to_raw, it is no longer neededRalf Jung-5/+0
2024-03-18add_retag: ensure box-to-raw-ptr casts are preserved for MiriRalf Jung-10/+34
2024-03-18do not eat nested exprs result in format args visitorRémy Rakic-2/+1
2024-03-18Rollup merge of #122656 - RalfJung:simplify-cfg, r=compiler-errorsMatthias Krüger-6/+9
simplify_cfg: rename some passes so that they make more sense I was extremely confused by `SimplifyCfg::ElaborateDrops`, since it runs way later than drop elaboration. It is used e.g. in `mir-opt/retag.rs` even though that pass doesn't care about drop elaboration at all. "Early opt" is also very confusing since that makes it sounds like it runs early during optimizations, i.e. on runtime MIR, but actually it runs way before that. So I decided to rename - early-opt -> post-analysis - elaborate-drops -> pre-optimizations I am open to other suggestions.
2024-03-18Rollup merge of #122654 - RalfJung:interpret-comment, r=matthiaskrgrMatthias Krüger-0/+2
interpret/memory: explain why we use == on bool This came up in https://github.com/rust-lang/rust/pull/122636.
2024-03-18Rollup merge of #122639 - omahs:patch-2, r=estebankMatthias Krüger-2/+2
Fix typos Fix typos
2024-03-18Auto merge of #121652 - estebank:move-in-loop-break-condition, r=Nadrierilbors-5/+257
Detect when move of !Copy value occurs within loop and should likely not be cloned When encountering a move error on a value within a loop of any kind, identify if the moved value belongs to a call expression that should not be cloned and avoid the semantically incorrect suggestion. Also try to suggest moving the call expression outside of the loop instead. ``` error[E0382]: use of moved value: `vec` --> $DIR/recreating-value-in-loop-condition.rs:6:33 | LL | let vec = vec!["one", "two", "three"]; | --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait LL | while let Some(item) = iter(vec).next() { | ----------------------------^^^-------- | | | | | value moved here, in previous iteration of loop | inside of this loop | note: consider changing this parameter type in function `iter` to borrow instead if owning the value isn't necessary --> $DIR/recreating-value-in-loop-condition.rs:1:17 | LL | fn iter<T>(vec: Vec<T>) -> impl Iterator<Item = T> { | ---- ^^^^^^ this parameter takes ownership of the value | | | in this function help: consider moving the expression out of the loop so it is only moved once | LL ~ let mut value = iter(vec); LL ~ while let Some(item) = value.next() { | ``` We use the presence of a `break` in the loop that would be affected by the moved value as a heuristic for "shouldn't be cloned". Fix https://github.com/rust-lang/rust/issues/121466. --- *Point at continue and break that might be in the wrong place* Sometimes move errors are because of a misplaced `continue`, but we didn't surface that anywhere. Now when there are more than one set of nested loops we show them out and point at the `continue` and `break` expressions within that might need to go elsewhere. ``` error[E0382]: use of moved value: `foo` --> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18 | LL | for foo in foos { | --- | | | this reinitialization might get skipped | move occurs because `foo` has type `String`, which does not implement the `Copy` trait ... LL | for bar in &bars { | ---------------- inside of this loop ... LL | baz.push(foo); | --- value moved here, in previous iteration of loop ... LL | qux.push(foo); | ^^^ value used here after move | note: verify that your loop breaking logic is correct --> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17 | LL | for foo in foos { | --------------- ... LL | for bar in &bars { | ---------------- ... LL | continue; | ^^^^^^^^ this `continue` advances the loop at line 33 help: consider moving the expression out of the loop so it is only moved once | LL ~ let mut value = baz.push(foo); LL ~ for bar in &bars { LL | ... LL | if foo == *bar { LL ~ value; | help: consider cloning the value if the performance cost is acceptable | LL | baz.push(foo.clone()); | ++++++++ ``` Fix https://github.com/rust-lang/rust/issues/92531.
2024-03-18Auto merge of #122627 - RalfJung:collector-stack-space, r=compiler-errorsbors-4/+8
collector: move ensure_sufficient_stack out of the loop According to the docs this call has some overhead to putting it inside the loop doesn't seem like a good idea. r? `@oli-obk`
2024-03-17Move `suggest_hoisting_call_outside_loop` out of `suggest_cloning`Esteban Küber-6/+3
2024-03-17Move `Visitor` impl out to the `mod` levelEsteban Küber-22/+22
2024-03-17Point at `continue` and `break` that might be in the wrong placeEsteban Küber-33/+130
Sometimes move errors are because of a misplaced `continue`, but we didn't surface that anywhere. Now when there are more than one set of nested loops we show them out and point at the `continue` and `break` expressions within that might need to go elsewhere. ``` error[E0382]: use of moved value: `foo` --> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18 | LL | for foo in foos { | --- | | | this reinitialization might get skipped | move occurs because `foo` has type `String`, which does not implement the `Copy` trait ... LL | for bar in &bars { | ---------------- inside of this loop ... LL | baz.push(foo); | --- value moved here, in previous iteration of loop ... LL | qux.push(foo); | ^^^ value used here after move | note: verify that your loop breaking logic is correct --> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17 | LL | for foo in foos { | --------------- ... LL | for bar in &bars { | ---------------- ... LL | continue; | ^^^^^^^^ this `continue` advances the loop at line 33 help: consider moving the expression out of the loop so it is only moved once | LL ~ let mut value = baz.push(foo); LL ~ for bar in &bars { LL | ... LL | if foo == *bar { LL ~ value; | help: consider cloning the value if the performance cost is acceptable | LL | baz.push(foo.clone()); | ++++++++ ``` Fix #92531.
2024-03-17Detect when move of `!Copy` value occurs within `loop` and should likely not ↵Esteban Küber-3/+161
be cloned When encountering a move error on a value within a loop of any kind, identify if the moved value belongs to a call expression that should not be cloned and avoid the semantically incorrect suggestion. Also try to suggest moving the call expression outside of the loop instead. ``` error[E0382]: use of moved value: `vec` --> $DIR/recreating-value-in-loop-condition.rs:6:33 | LL | let vec = vec!["one", "two", "three"]; | --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait LL | while let Some(item) = iter(vec).next() { | ----------------------------^^^-------- | | | | | value moved here, in previous iteration of loop | inside of this loop | note: consider changing this parameter type in function `iter` to borrow instead if owning the value isn't necessary --> $DIR/recreating-value-in-loop-condition.rs:1:17 | LL | fn iter<T>(vec: Vec<T>) -> impl Iterator<Item = T> { | ---- ^^^^^^ this parameter takes ownership of the value | | | in this function help: consider moving the expression out of the loop so it is only moved once | LL ~ let mut value = iter(vec); LL ~ while let Some(item) = value.next() { | ``` We use the presence of a `break` in the loop that would be affected by the moved value as a heuristic for "shouldn't be cloned". Fix #121466.
2024-03-17simplify_cfg: rename some passes so that they make more senseRalf Jung-6/+9
2024-03-17interpret/memory: explain why we use == on boolRalf Jung-0/+2
2024-03-17Rollup merge of #122636 - matthiaskrgr:compl3, r=compiler-errorsMatthias Krüger-11/+4
some minor code simplifications