about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
AgeCommit message (Collapse)AuthorLines
2025-01-28Properly check that array length is valid type during built-in unsizing in indexMichael Goulet-1/+4
2025-01-28Rollup merge of #136066 - compiler-errors:local-spans, r=lcnrMatthias Krüger-15/+26
Pass spans to `perform_locally_in_new_solver` Nothing changes yet, but we may be able to use these spans in the future once we start dealing w the response region constraints better. r? lcnr
2025-01-28Suggest considering casting fn item as fn pointer in more casesmu001999-6/+42
2025-01-27Rollup merge of #136114 - compiler-errors:more-idents, r=jieyouxuGuillaume Gomez-4/+8
Use identifiers more in diagnostics code This should make the diagnostics code slightly more correct when rendering idents in mixed crate edition situations. Kinda a no-op, but a cleanup regardless. r? oli-obk or reassign
2025-01-27Use identifiers in diagnostics more oftenMichael Goulet-4/+8
2025-01-26Compiler: Finalize dyn compatibility renamingLeón Orell Valerian Liehr-6/+5
2025-01-25Pass spans to perform_locally_in_new_solverMichael Goulet-15/+26
2025-01-25Add a suggestion to cast target_feature fn items to fn pointers.Luca Versari-0/+3
See https://github.com/rust-lang/rust/pull/134090#issuecomment-2612197095 for the motivation behind this suggestion.
2025-01-24Rollup merge of #135949 - estebank:shorten-ty, r=davidtwcoMatthias Krüger-9/+10
Use short type string in E0308 secondary span label We were previously printing the full type on the "this expression has type" label. ``` error[E0308]: mismatched types --> $DIR/secondary-label-with-long-type.rs:8:9 | LL | let () = x; | ^^ - this expression has type `((..., ..., ..., ...), ..., ..., ...)` | | | expected `((..., ..., ..., ...), ..., ..., ...)`, found `()` | = note: expected tuple `((..., ..., ..., ...), ..., ..., ...)` found unit type `()` = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/secondary-label-with-long-type/secondary-label-with-long-type.long-type-3987761834644699448.txt' = note: consider using `--verbose` to print the full type name to the console ``` Reported in a comment of #135919.
2025-01-24Rollup merge of #135749 - compiler-errors:param-ordering, r=davidtwcoMatthias Krüger-138/+121
Do not assume const params are printed after type params Fixes #135737
2025-01-24Revert "Rollup merge of #135914 - compiler-errors:vanquish-query-norm, ↵Michael Goulet-14/+10
r=jackh726" This reverts commit 556d901c36511560e0ae8ce3058507121a2fb2f0, reversing changes made to be15391703babf217aaef3c854213a7fcd70e00b.
2025-01-24Do not assume const params are printed after type paramsMichael Goulet-138/+121
2025-01-24Auto merge of #135272 - BoxyUwU:generic_arg_infer_reliability_2, ↵bors-49/+47
r=compiler-errors Forbid usage of `hir` `Infer` const/ty variants in ambiguous contexts The feature `generic_arg_infer` allows providing `_` as an argument to const generics in order to infer them. This introduces a syntactic ambiguity as to whether generic arguments are type or const arguments. In order to get around this we introduced a fourth `GenericArg` variant, `Infer` used to represent `_` as an argument to generic parameters when we don't know if its a type or a const argument. This made hir visitors that care about `TyKind::Infer` or `ConstArgKind::Infer` very error prone as checking for `TyKind::Infer`s in `visit_ty` would find *some* type infer arguments but not *all* of them as they would sometimes be lowered to `GenericArg::Infer` instead. Additionally the `visit_infer` method would previously only visit `GenericArg::Infer` not *all* infers (e.g. `TyKind::Infer`), this made it very easy to override `visit_infer` and expect it to visit all infers when in reality it would only visit *some* infers. --- This PR aims to fix those issues by making the `TyKind` and `ConstArgKind` types generic over whether the infer types/consts are represented by `Ty/ConstArgKind::Infer` or out of line (e.g. by a `GenericArg::Infer` or accessible by overiding `visit_infer`). We then make HIR Visitors convert all const args and types to the versions where infer vars are stored out of line and call `visit_infer` in cases where a `Ty`/`Const` would previously have had a `Ty/ConstArgKind::Infer` variant: API Summary ```rust enum AmbigArg {} enum Ty/ConstArgKind<Unambig = ()> { ... Infer(Unambig), } impl Ty/ConstArg { fn try_as_ambig_ty/ct(self) -> Option<Ty/ConstArg<AmbigArg>>; } impl Ty/ConstArg<AmbigArg> { fn as_unambig_ty/ct(self) -> Ty/ConstArg; } enum InferKind { Ty(Ty), Const(ConstArg), Ambig(InferArg), } trait Visitor { ... fn visit_ty/const_arg(&mut self, Ty/ConstArg<AmbigArg>) -> Self::Result; fn visit_infer(&mut self, id: HirId, sp: Span, kind: InferKind) -> Self::Result; } // blanket impl'd, not meant to be overriden trait VisitorExt { fn visit_ty/const_arg_unambig(&mut self, Ty/ConstArg) -> Self::Result; } fn walk_unambig_ty/const_arg(&mut V, Ty/ConstArg) -> Self::Result; fn walk_ty/const_arg(&mut V, Ty/ConstArg<AmbigArg>) -> Self::Result; ``` The end result is that `visit_infer` visits *all* infer args and is also the *only* way to visit an infer arg, `visit_ty` and `visit_const_arg` can now no longer encounter a `Ty/ConstArgKind::Infer`. Representing this in the type system means that it is now very difficult to mess things up, either accessing `TyKind::Infer` "just works" and you won't miss *some* type infers- or it doesn't work and you have to look at `visit_infer` or some `GenericArg::Infer` which forces you to think about the full complexity involved. Unfortunately there is no lint right now about explicitly matching on uninhabited variants, I can't find the context for why this is the case :woman_shrugging: I'm not convinced the framing of un/ambig ty/consts is necessarily the right one but I'm not sure what would be better. I somewhat like calling them full/partial types based on the fact that `Ty<Partial>`/`Ty<Full>` directly specifies how many of the type kinds are actually represented compared to `Ty<Ambig>` which which leaves that to the reader to figure out based on the logical consequences of it the type being in an ambiguous position. --- tool changes have been modified in their own commits for easier reviewing by anyone getting cc'd from subtree changes. I also attempted to split out "bug fixes arising from the refactoring" into their own commit so they arent lumped in with a big general refactor commit Fixes #112110
2025-01-24Rollup merge of #135914 - compiler-errors:vanquish-query-norm, r=jackh726Matthias Krüger-10/+14
Remove usages of `QueryNormalizer` in the compiler I want to get rid of the `QueryNormalizer`, possibly changing it to be special cased just for normalizing erasing regions, or perhaps adapting `normalize_erasing_regions` to use the assoc type normalizer if caching is sufficient and removing it altogther. This removes the last two usages of `.query_normalize` in the *compiler*. There are a few usages left in rustdoc and clippy, which exist only because the query normalizer is more resilient to errors and non-well-formed alias types. I will remove those next. r? lcnr or reassign
2025-01-24Use short type string in E0308 secondary span labelEsteban Küber-9/+10
We were previously printing the full type on the "this expression has type" label. ``` error[E0308]: mismatched types --> $DIR/secondary-label-with-long-type.rs:8:9 | LL | let () = x; | ^^ - this expression has type `((..., ..., ..., ...), ..., ..., ...)` | | | expected `((..., ..., ..., ...), ..., ..., ...)`, found `()` | = note: expected tuple `((..., ..., ..., ...), ..., ..., ...)` found unit type `()` = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/secondary-label-with-long-type/secondary-label-with-long-type.long-type-3987761834644699448.txt' = note: consider using `--verbose` to print the full type name to the console ``` Reported in a comment of #135919.
2025-01-23Rollup merge of #135492 - metamuffin:bug-invalid-await-suggest, ↵Matthias Krüger-0/+12
r=compiler-errors Add missing check for async body when suggesting await on futures. Currently the compiler suggests adding `.await` to resolve some type conflicts without checking if the conflict happens in an async context. This can lead to the compiler suggesting `.await` in function signatures where it is invalid. Example: ```rs trait A { fn a() -> impl Future<Output = ()>; } struct B; impl A for B { fn a() -> impl Future<Output = impl Future<Output = ()>> { async { async { () } } } } ``` ``` error[E0271]: expected `impl Future<Output = impl Future<Output = ()>>` to be a future that resolves to `()`, but it resolves to `impl Future<Output = ()>` --> bug.rs:6:15 | 6 | fn a() -> impl Future<Output = impl Future<Output = ()>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found future | note: calling an async function returns a future --> bug.rs:6:15 | 6 | fn a() -> impl Future<Output = impl Future<Output = ()>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `A::{synthetic#0}` --> bug.rs:2:27 | 2 | fn a() -> impl Future<Output = ()>; | ^^^^^^^^^^^ required by this bound in `A::{synthetic#0}` help: consider `await`ing on the `Future` | 6 | fn a() -> impl Future<Output = impl Future<Output = ()>>.await { | ++++++ ``` The documentation of suggest_await_on_expect_found (`compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs:156`) even mentions such a check but does not actually implement it. This PR adds that check to ensure `.await` is only suggested within async blocks. There were 3 unit tests whose expected output needed to be changed because they had the suggestion outside of async. One of them (`tests/ui/async-await/dont-suggest-missing-await.rs`) actually tests that exact problem but expects it to be present. Thanks to `@llenck` for initially noticing the bug and helping with fixing it
2025-01-23`visit_x_unambig`Boxy-9/+9
2025-01-23Split hir `TyKind` and `ConstArgKind` in two and update `hir::Visitor`Boxy-40/+40
2025-01-23Make `hir::TyKind::TraitObject` use tagged ptrBoxy-9/+7
2025-01-23Remove query normalize from dropck outlives type opMichael Goulet-10/+14
2025-01-22Rollup merge of #135866 - BoxyUwU:dont_pick_fnptr_nested_goals, r=lcnrMatthias Krüger-2/+21
Don't pick `T: FnPtr` nested goals as the leaf goal in diagnostics for new solver r? `@lcnr` See `tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.rs` for a minimized example of what code this affects the diagnostics off. The output of running nightly `-Znext-solver` on that test is the following: ``` error[E0277]: the trait bound `Foo: Trait` is not satisfied --> src/lib.rs:14:20 | 14 | requires_trait(Foo); | -------------- ^^^ the trait `FnPtr` is not implemented for `Foo` | | | required by a bound introduced by this call | note: required for `Foo` to implement `Trait` --> src/lib.rs:7:16 | 7 | impl<T: FnPtr> Trait for T {} | ----- ^^^^^ ^ | | | unsatisfied trait bound introduced here note: required by a bound in `requires_trait` --> src/lib.rs:11:22 | 11 | fn requires_trait<T: Trait>(_: T) {} | ^^^^^ required by this bound in `requires_trait` ``` Part of rust-lang/trait-system-refactor-initiative#148
2025-01-22Rollup merge of #135816 - BoxyUwU:root_normalizes_to_goal_ice, r=lcnrMatthias Krüger-64/+47
Use `structurally_normalize` instead of manual `normalizes-to` goals in alias relate errors r? `@lcnr` I added `structurally_normalize_term` so that code that is generic over ty or const can use the structurally normalize helpers. See `tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.rs` for a description of the reason for the (now fixed) ICEs
2025-01-22Refactor dyn-compatibility error and suggestionsTaylor Cramer-80/+108
This CL makes a number of small changes to dyn compatibility errors: - "object safety" has been renamed to "dyn-compatibility" throughout - "Convert to enum" suggestions are no longer generated when there exists a type-generic impl of the trait or an impl for `dyn OtherTrait` - Several error messages are reorganized for user readability Additionally, the dyn compatibility error creation code has been split out into functions. cc #132713 cc #133267
2025-01-22Rename `structurally_normalize` to `structurally_normalize_ty`Boxy-4/+4
2025-01-22Use `structurally_normalize` instead of manual `normalizes-to` goalsBoxy-60/+43
2025-01-22Don't pick `T: FnPtr` nested goalsBoxy-2/+21
2025-01-21Rollup merge of #135706 - compiler-errors:elaborate, r=lcnrMatthias Krüger-9/+11
Move `supertrait_def_ids` into the elaborate module like all other fns It's strange that this is the only elaborate-like fn on tcx. r? lcnr
2025-01-21Auto merge of #134299 - RalfJung:remove-start, r=compiler-errorsbors-14/+0
remove support for the (unstable) #[start] attribute As explained by `@Noratrieb:` `#[start]` should be deleted. It's nothing but an accidentally leaked implementation detail that's a not very useful mix between "portable" entrypoint logic and bad abstraction. I think the way the stable user-facing entrypoint should work (and works today on stable) is pretty simple: - `std`-using cross-platform programs should use `fn main()`. the compiler, together with `std`, will then ensure that code ends up at `main` (by having a platform-specific entrypoint that gets directed through `lang_start` in `std` to `main` - but that's just an implementation detail) - `no_std` platform-specific programs should use `#![no_main]` and define their own platform-specific entrypoint symbol with `#[no_mangle]`, like `main`, `_start`, `WinMain` or `my_embedded_platform_wants_to_start_here`. most of them only support a single platform anyways, and need cfg for the different platform's ways of passing arguments or other things *anyways* `#[start]` is in a super weird position of being neither of those two. It tries to pretend that it's cross-platform, but its signature is a total lie. Those arguments are just stubbed out to zero on ~~Windows~~ wasm, for example. It also only handles the platform-specific entrypoints for a few platforms that are supported by `std`, like Windows or Unix-likes. `my_embedded_platform_wants_to_start_here` can't use it, and neither could a libc-less Linux program. So we have an attribute that only works in some cases anyways, that has a signature that's a total lie (and a signature that, as I might want to add, has changed recently, and that I definitely would not be comfortable giving *any* stability guarantees on), and where there's a pretty easy way to get things working without it in the first place. Note that this feature has **not** been RFCed in the first place. *This comment was posted [in May](https://github.com/rust-lang/rust/issues/29633#issuecomment-2088596042) and so far nobody spoke up in that issue with a usecase that would require keeping the attribute.* Closes https://github.com/rust-lang/rust/issues/29633 try-job: x86_64-gnu-nopt try-job: x86_64-msvc-1 try-job: x86_64-msvc-2 try-job: test-various
2025-01-21Move supertrait_def_ids into the elaborate module like all other fnsMichael Goulet-9/+11
2025-01-21remove support for the #[start] attributeRalf Jung-14/+0
2025-01-21Auto merge of #133830 - compiler-errors:span-key, r=lcnrbors-147/+71
Rework dyn trait lowering to stop being so intertwined with trait alias expansion This PR reworks the trait object lowering code to stop handling trait aliases so funky, and removes the `TraitAliasExpander` in favor of a much simpler design. This refactoring is important for making the code that I'm writing in https://github.com/rust-lang/rust/pull/133397 understandable and easy to maintain, so the diagnostics regressions are IMO inevitable. In the old trait object lowering code, we used to be a bit sloppy with the lists of traits in their unexpanded and expanded forms. This PR largely rewrites this logic to expand the trait aliases *once* and handle them more responsibly throughout afterwards. Please review this with whitespace disabled. r? lcnr
2025-01-19Manual cleanup of some `is_{or_none|some_and}` usagesYotam Ofek-1/+2
2025-01-19Run `clippy --fix` for `unnecessary_map_or` lintYotam Ofek-2/+1
2025-01-18Get rid of `ToPolyTraitRef`Michael Goulet-110/+112
2025-01-18Rollup merge of #135639 - lqd:trivial-builtin-impls, r=lcnrMatthias Krüger-2/+2
new solver: prefer trivial builtin impls As discussed [on zulip](https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/needs_help.3A.20trivial.20builtin.20impls), this PR: - adds a new `BuiltinImplSource::Trivial` source, and marks the `Sized` builtin impls as trivial - prefers these trivial builtin impls in `merge_trait_candidates` The comments can likely be wordsmithed a bit better, and I ~stole~ was inspired by the old solver ones. Let me know how you want them improved. When enabling the new solver for tests, 3 UI tests now pass: - `regions/issue-26448-1.rs` and its sibling `regions/issue-26448-2.rs` were rejected by the new solver but accepted by the old one - and `issues/issue-42796.rs` where the old solver emitted some overflow errors in addition to the expected error (For some reason one of these tests is run-pass, but I can take care of that another day) r? lcnr
2025-01-18Auto merge of #135618 - lcnr:coherence-unknown, r=compiler-errorsbors-24/+45
add cache to `AmbiguityCausesVisitor` fixes #135457, alternative to #135524. cc https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/new-solver.20hang.20.23135457 r? `@compiler-errors`
2025-01-17new solver: prefer trivial builtin impls over where-clausesRémy Rakic-2/+2
for now, only builtin `Sized` impls are tracked as being `Trivial`
2025-01-17add cache to `AmbiguityCausesVisitor`lcnr-2/+12
2025-01-17Rollup merge of #135558 - estebank:issue-133316, r=chenyukangMatthias Krüger-0/+8
Detect if-else chains with a missing final else in type errors ``` error[E0308]: `if` and `else` have incompatible types --> $DIR/if-else-chain-missing-else.rs:12:12 | LL | let x = if let Ok(x) = res { | ______________- LL | | x | | - expected because of this LL | | } else if let Err(e) = res { | | ____________^ LL | || return Err(e); LL | || }; | || ^ | ||_____| | |_____`if` and `else` have incompatible types | expected `i32`, found `()` | = note: `if` expressions without `else` evaluate to `()` = note: consider adding an `else` block that evaluates to the expected type ``` We probably want a longer explanation and fewer spans on this case. Partially address #133316.
2025-01-16Add missing check for async body when suggesting await on futures.metamuffin-0/+12
2025-01-16Detect if-else chains with a missing final else in type errorsEsteban Küber-0/+8
``` error[E0308]: `if` and `else` have incompatible types --> $DIR/if-else-chain-missing-else.rs:12:12 | LL | let x = if let Ok(x) = res { | ______________- LL | | x | | - expected because of this LL | | } else if let Err(e) = res { | | ____________^ LL | || return Err(e); LL | || }; | || ^ | ||_____| | |_____`if` and `else` have incompatible types | expected `i32`, found `()` | = note: `if` expressions without `else` evaluate to `()` = note: consider adding an `else` block that evaluates to the expected type ``` We probably want a longer explanation and fewer spans on this case. Partially address #133316.
2025-01-15Rollup merge of #135498 - compiler-errors:dyn-upcasting-completeness, r=lcnrGuillaume Gomez-1/+17
Prefer lower `TraitUpcasting` candidates in selection Fixes #135463. The underlying cause is this ambiguity, but it's more clear (and manifests as a coercion error, rather than a MIR validation error) when it's written the way I did in the UI test. Sorry this is cursed r? lcnr
2025-01-15Auto merge of #134353 - oli-obk:safe-target-feature-unsafe-by-default, ↵bors-27/+67
r=wesleywiser Treat safe target_feature functions as unsafe by default [less invasive variant] This unblocks * #134090 As I stated in https://github.com/rust-lang/rust/pull/134090#issuecomment-2541332415 I think the previous impl was too easy to get wrong, as by default it treated safe target feature functions as safe and had to add additional checks for when they weren't. Now the logic is inverted. By default they are unsafe and you have to explicitly handle safe target feature functions. This is the less (imo) invasive variant of #134317, as it doesn't require changing the Safety enum, so it only affects FnDefs and nothing else, as it should.
2025-01-15Avoid notes that only make sense for unsafe functionsOli Scherer-2/+4
2025-01-15Try to render shorthand differentlyOli Scherer-3/+9
2025-01-15Render fn defs with target_features attrs with the attribute [second site]Oli Scherer-20/+40
2025-01-15Hide the internal unsafety of safe target_feature fn itemsOli Scherer-2/+14
2025-01-15avoid running the overlap check twicelcnr-22/+33
2025-01-14Rollup merge of #135380 - compiler-errors:mismatch-valtree, r=lcnrJubilee-2/+3
Make sure we can produce `ConstArgHasWrongType` errors for valtree consts I forgot about `ty::ConstKind::Value` in #134771. The error message here could use some work -- both in the new trait solver and the old trait solver. But unrelated to the issue here. Fixes https://github.com/rust-lang/rust/issues/135361 -- this was only ICEing in coherence because coherence uses the new trait solver, but I don't think the minimization is worth committing compared to the test I added. r? ```@lcnr``` or ```@BoxyUwU```
2025-01-15Rework trait expansion to happen once explicitlyMichael Goulet-147/+71