about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits
AgeCommit message (Collapse)AuthorLines
2025-04-08Instantiate higher-ranked transmute goalMichael Goulet-3/+3
2025-04-08Rollup merge of #139509 - xizheyin:issue-139359, r=lcnrMatthias Krüger-7/+7
clean: remove Deref<Target=RegionKind> impl for Region and use `.kind()` Closes #139359 r? `@lcnr`
2025-04-08clean code: remove Deref<Target=RegionKind> impl for Region and use `.kind()`xizheyin-7/+7
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
2025-04-05Fix trait upcasting to dyn type with no principal when there are projectionsMichael Goulet-14/+24
2025-04-04Auto merge of #138785 - lcnr:typing-mode-borrowck, r=compiler-errors,oli-obkbors-1/+7
add `TypingMode::Borrowck` Shares the first commit with #138499, doesn't really matter which PR to land first :blush: :grin: Introduces `TypingMode::Borrowck` which unlike `TypingMode::Analysis`, uses the hidden type computed by HIR typeck as the initial value of opaques instead of an unconstrained infer var. This is a part of https://github.com/rust-lang/types-team/issues/129. Using this new `TypingMode` is unfortunately a breaking change for now, see tests/ui/impl-trait/non-defining-uses/as-projection-term.rs. Using an inference variable as the initial value results in non-defining uses in the defining scope. We therefore only enable it if with `-Znext-solver=globally` or `-Ztyping-mode-borrowck` To do that the PR contains the following changes: - `TypeckResults::concrete_opaque_type` are already mapped to the definition of the opaque type - writeback now checks that the non-lifetime parameters of the opaque are universal - for this, `fn check_opaque_type_parameter_valid` is moved from `rustc_borrowck` to `rustc_trait_selection` - we add a new `query type_of_opaque_hir_typeck` which, using the same visitors as MIR typeck, attempts to merge the hidden types from HIR typeck from all defining scopes - done by adding a `DefiningScopeKind` flag to toggle between using borrowck and HIR typeck - the visitors stop checking that the MIR type matches the HIR type. This is trivial as the HIR type are now used as the initial hidden types of the opaque. This check is useful as a safeguard when not using `TypingMode::Borrowck`, but adding it to the new structure is annoying and it's not soundness critical, so I intend to not add it back. - add a `TypingMode::Borrowck` which behaves just like `TypingMode::Analysis` except when normalizing opaque types - it uses `type_of_opaque_hir_typeck(opaque)` as the initial value after replacing its regions with new inference vars - it uses structural lookup in the new solver fixes #112201, fixes #132335, fixes #137751 r? `@compiler-errors` `@oli-obk`
2025-04-04Auto merge of #120706 - Bryanskiy:leak, r=lcnrbors-15/+29
Initial support for auto traits with default bounds This PR is part of ["MCP: Low level components for async drop"](https://github.com/rust-lang/compiler-team/issues/727) Tracking issue: #138781 Summary: https://github.com/rust-lang/rust/pull/120706#issuecomment-1934006762 ### Intro Sometimes we want to use type system to express specific behavior and provide safety guarantees. This behavior can be specified by various "marker" traits. For example, we use `Send` and `Sync` to keep track of which types are thread safe. As the language develops, there are more problems that could be solved by adding new marker traits: - to forbid types with an async destructor to be dropped in a synchronous context a trait like `SyncDrop` could be used [Async destructors, async genericity and completion futures](https://sabrinajewson.org/blog/async-drop). - to support [scoped tasks](https://without.boats/blog/the-scoped-task-trilemma/) or in a more general sense to provide a [destruction guarantee](https://zetanumbers.github.io/book/myosotis.html) there is a desire among some users to see a `Leak` (or `Forget`) trait. - Withoutboats in his [post](https://without.boats/blog/changing-the-rules-of-rust/) reflected on the use of `Move` trait instead of a `Pin`. All the traits proposed above are supposed to be auto traits implemented for most types, and usually implemented automatically by compiler. For backward compatibility these traits have to be added implicitly to all bound lists in old code (see below). Adding new default bounds involves many difficulties: many standard library interfaces may need to opt out of those default bounds, and therefore be infected with confusing `?Trait` syntax, migration to a new edition may contain backward compatibility holes, supporting new traits in the compiler can be quite difficult and so forth. Anyway, it's hard to evaluate the complexity until we try the system on a practice. In this PR we introduce new optional lang items for traits that are added to all bound lists by default, similarly to existing `Sized`. The examples of such traits could be `Leak`, `Move`, `SyncDrop` or something else, it doesn't matter much right now (further I will call them `DefaultAutoTrait`'s). We want to land this change into rustc under an option, so it becomes available in bootstrap compiler. Then we'll be able to do standard library experiments with the aforementioned traits without adding hundreds of `#[cfg(not(bootstrap))]`s. Based on the experiments, we can come up with some scheme for the next edition, in which such bounds are added in a more targeted way, and not just everywhere. Most of the implementation is basically a refactoring that replaces hardcoded uses of `Sized` with iterating over a list of traits including both `Sized` and the new traits when `-Zexperimental-default-bounds` is enabled (or just `Sized` as before, if the option is not enabled). ### Default bounds for old editions All existing types, including generic parameters, are considered `Leak`/`Move`/`SyncDrop` and can be forgotten, moved or destroyed in generic contexts without specifying any bounds. New types that cannot be, for example, forgotten and do not implement `Leak` can be added at some point, and they should not be usable in such generic contexts in existing code. To both maintain this property and keep backward compatibility with existing code, the new traits should be added as default bounds _everywhere_ in previous editions. Besides the implicit `Sized` bound contexts that includes supertrait lists and trait lists in trait objects (`dyn Trait1 + ... + TraitN`). Compiler should also generate implicit `DefaultAutoTrait` implementations for foreign types (`extern { type Foo; }`) because they are also currently usable in generic contexts without any bounds. #### Supertraits Adding the new traits as supertraits to all existing traits is potentially necessary, because, for example, using a `Self` param in a trait's associated item may be a breaking change otherwise: ```rust trait Foo: Sized { fn new() -> Option<Self>; // ERROR: `Option` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait` } // desugared `Option` enum Option<T: DefaultAutoTrait + Sized> { Some(T), None, } ``` However, default supertraits can significantly affect compiler performance. For example, if we know that `T: Trait`, the compiler would deduce that `T: DefaultAutoTrait`. It also implies proving `F: DefaultAutoTrait` for each field `F` of type `T` until an explicit impl is be provided. If the standard library is not modified, then even traits like `Copy` or `Send` would get these supertraits. In this PR for optimization purposes instead of adding default supertraits, bounds are added to the associated items: ```rust // Default bounds are generated in the following way: trait Trait { fn foo(&self) where Self: DefaultAutoTrait {} } // instead of this: trait Trait: DefaultAutoTrait { fn foo(&self) {} } ``` It is not always possible to do this optimization because of backward compatibility: ```rust pub trait Trait<Rhs = Self> {} pub trait Trait1 : Trait {} // ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait` ``` or ```rust trait Trait { type Type where Self: Sized; } trait Trait2<T> : Trait<Type = T> {} // ERROR: `???` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait` ``` Therefore, `DefaultAutoTrait`'s are still being added to supertraits if the `Self` params or type bindings were found in the trait header. #### Trait objects Trait objects requires explicit `+ Trait` bound to implement corresponding trait which is not backward compatible: ```rust fn use_trait_object(x: Box<dyn Trait>) { foo(x) // ERROR: `foo` requires `DefaultAutoTrait`, but `dyn Trait` is not `DefaultAutoTrait` } // implicit T: DefaultAutoTrait here fn foo<T>(_: T) {} ``` So, for a trait object `dyn Trait` we should add an implicit bound `dyn Trait + DefaultAutoTrait` to make it usable, and allow relaxing it with a question mark syntax `dyn Trait + ?DefaultAutoTrait` when it's not necessary. #### Foreign types If compiler doesn't generate auto trait implementations for a foreign type, then it's a breaking change if the default bounds are added everywhere else: ```rust // implicit T: DefaultAutoTrait here fn foo<T: ?Sized>(_: &T) {} extern "C" { type ExternTy; } fn forward_extern_ty(x: &ExternTy) { foo(x); // ERROR: `foo` requires `DefaultAutoTrait`, but `ExternTy` is not `DefaultAutoTrait` } ``` We'll have to enable implicit `DefaultAutoTrait` implementations for foreign types at least for previous editions: ```rust // implicit T: DefaultAutoTrait here fn foo<T: ?Sized>(_: &T) {} extern "C" { type ExternTy; } impl DefaultAutoTrait for ExternTy {} // implicit impl fn forward_extern_ty(x: &ExternTy) { foo(x); // OK } ``` ### Unresolved questions New default bounds affect all existing Rust code complicating an already complex type system. - Proving an auto trait predicate requires recursively traversing the type and proving the predicate for it's fields. This leads to a significant performance regression. Measurements for the stage 2 compiler build show up to 3x regression. - We hope that fast path optimizations for well known traits could mitigate such regressions at least partially. - New default bounds trigger some compiler bugs in both old and new trait solver. - With new default bounds we encounter some trait solver cycle errors that break existing code. - We hope that these cases are bugs that can be addressed in the new trait solver. Also migration to a new edition could be quite ugly and enormous, but that's actually what we want to solve. For other issues there's a chance that they could be solved by a new solver.
2025-04-03Initial support for auto traits with default boundsBryanskiy-15/+29
2025-04-03add `TypingMode::Borrowck`lcnr-1/+7
2025-04-02Auto merge of #139018 - oli-obk:incremental-trait-impls, r=compiler-errorsbors-1/+1
Various local trait item iteration cleanups Adding a trait impl for `Foo` unconditionally affected all queries that are interested in a completely independent trait `Bar`. Perf has no effect on this. We probably don't have a good perf test for this tho. r? `@compiler-errors` I am unsure about https://github.com/rust-lang/rust/pull/139018/commits/9d05efb66f7b599eeacb5d2456f844fe4768e865 as it doesn't improve anything wrt incremental, because we still do all the checks for valid `Drop` impls, which subsequently will still invoke many queries and basically keep the depgraph the same. I want to do https://github.com/rust-lang/rust/blob/9549077a47099dc826039c051b528d1013740e6f/compiler/rustc_middle/src/ty/trait_def.rs#L141 but would leave that to a follow-up PR, this one changes enough things as it is
2025-04-02Fetch the destructor constness lazilyOli Scherer-1/+1
2025-04-02Rollup merge of #138941 - compiler-errors:receiver-is-dispatchable-bounds, ↵Stuart Cook-13/+22
r=BoxyUwU Do not mix normalized and unnormalized caller bounds when constructing param-env for `receiver_is_dispatchable` See comments in code and in test I added. r? `@BoxyUwU` since you reviewed the last PR, or reassign Fixes #138937
2025-03-31increment depth of nested obligationslcnr-38/+38
2025-03-31Rollup merge of #138176 - compiler-errors:rigid-sized-obl, r=lcnrMatthias Krüger-15/+43
Prefer built-in sized impls (and only sized impls) for rigid types always This PR changes the confirmation of `Sized` obligations to unconditionally prefer the built-in impl, even if it has nested obligations. This also changes all other built-in impls (namely, `Copy`/`Clone`/`DiscriminantKind`/`Pointee`) to *not* prefer built-in impls over param-env impls. This aligns the old solver with the behavior of the new solver. --- In the old solver, we register many builtin candidates with the `BuiltinCandidate { has_nested: bool }` candidate kind. The precedence this candidate takes over other candidates is based on the `has_nested` field. We only prefer builtin impls over param-env candidates if `has_nested` is `false` https://github.com/rust-lang/rust/blob/2b4694a69804f89ff9d47d1a427f72c876f7f44c/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1804-L1866 Preferring param-env candidates when the builtin candidate has nested obligations *still* ends up leading to detrimental inference guidance, like: ```rust fn hello<T>() where (T,): Sized { let x: (_,) = Default::default(); // ^^ The `Sized` obligation on the variable infers `_ = T`. let x: (i32,) = x; // We error here, both a type mismatch and also b/c `T: Default` doesn't hold. } ``` Therefore this PR adjusts the candidate precedence of `Sized` obligations by making them a distinct candidate kind and unconditionally preferring them over all other candidate kinds. Special-casing `Sized` this way is necessary as there are a lot of traits with a `Sized` super-trait bound, so a `&'a str: From<T>` where-bound results in an elaborated `&'a str: Sized` bound. People tend to not add explicit where-clauses which overlap with builtin impls, so this tends to not be an issue for other traits. We don't know of any tests/crates which need preference for other builtin traits. As this causes builtin impls to diverge from user-written impls we would like to minimize the affected traits. Otherwise e.g. moving impls for tuples to std by using variadic generics would be a breaking change. For other builtin impls it's also easier for the preference of builtin impls over where-bounds to result in issues. --- There are two ways preferring builtin impls over where-bounds can be incorrect and undesirable: - applying the builtin impl results in undesirable region constraints. E.g. if only `MyType<'static>` implements `Copy` then a goal like `(MyType<'a>,): Copy` would require `'a == 'static` so we must not prefer it over a `(MyType<'a>,): Copy` where-bound - this is mostly not an issue for `Sized` as all `Sized` impls are builtin and don't add any region constraints not already required for the type to be well-formed - however, even with `Sized` this is still an issue if a nested goal also gets proven via a where-bound: [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=30377da5b8a88f654884ab4ebc72f52b) - if the builtin impl has associated types, we should not prefer it over where-bounds when normalizing that associated type. This can result in normalization adding more region constraints than just proving trait bounds. https://github.com/rust-lang/rust/issues/133044 - not an issue for `Sized` as it doesn't have associated types. r? lcnr
2025-03-30Do not mix normalized and unnormalized caller bounds when constructing ↵Michael Goulet-13/+22
param-env for receiver_is_dispatchable
2025-03-27Auto merge of #139012 - Zalathar:rollup-qgt5yfo, r=Zalatharbors-2/+4
Rollup of 10 pull requests Successful merges: - #130883 (Add environment variable query) - #138624 (Add mipsel maintainer) - #138672 (Avoiding calling queries when collecting active queries) - #138935 (Update wg-prio triagebot config) - #138946 (Un-bury chapters from the chapter list in rustc book) - #138964 (Implement lint against using Interner and InferCtxtLike in random compiler crates) - #138977 (Don't deaggregate InvocationParent just to reaggregate it again) - #138980 (Collect items referenced from var_debug_info) - #138985 (Use the correct binder scope for elided lifetimes in assoc consts) - #138987 (Always emit `native-static-libs` note, even if it is empty) r? `@ghost` `@rustbot` modify labels: rollup
2025-03-26Stop using Interner in the compiler randomlyMichael Goulet-2/+4
2025-03-24Instantiate binder before registering nested obligations for auto/built-in ↵Michael Goulet-32/+16
traits
2025-03-23Obligation::as_goalMichael Goulet-1/+1
2025-03-18Remove existing AFIDT implementationMichael Goulet-89/+3
2025-03-16Suppress must_use in compiler and toolsMichael Goulet-2/+2
2025-03-15Fold visit into tyMichael Goulet-8/+9
2025-03-15Squash fold into tyMichael Goulet-10/+7
2025-03-13Only prefer Sized candidates, and only if they certainly holdMichael Goulet-21/+17
2025-03-13Prefer built-in sized impls for rigid types alwaysMichael Goulet-5/+37
2025-03-13Auto merge of #138249 - compiler-errors:auto-self, r=lcnrbors-15/+1
Do not register `Self: AutoTrait` when confirming auto trait (in old solver) Every built-in auto impl for a trait goal like `Ty: Auto` immediately registers another obligation of `Ty: Auto` as one of its nested obligations, leading to us stressing the cycle detection machinery a lot more than we need to. This is because all traits have a `Self: Trait` predicate. To fix this, remove the call to `impl_or_trait_obligations` in `vtable_auto_impl`, since auto traits do not have where clauses. r? lcnr
2025-03-12Rollup merge of #138174 - compiler-errors:elaborate-unsize-self-pred, r=BoxyUwUMatthias Krüger-7/+12
Elaborate trait assumption in `receiver_is_dispatchable` Fixes #138172. See comment on the linked test. Probably not a fix for the general problem, bc I think this may still be incomplete for other weird `where` clauses on the receiver. But 🤷, supertraits seems like an obvious one to fix.
2025-03-11Elaborate param-env built for checking DispatchFromDyn for dyn compatMichael Goulet-7/+12
2025-03-10Remove AdtFlags::IS_ANONYMOUS and Copy/Clone condition for anonymous ADTMichael Goulet-9/+0
2025-03-09Rollup merge of #138040 - thaliaarchi:use-prelude-size-of.compiler, ↵Matthias Krüger-1/+1
r=compiler-errors compiler: Use `size_of` from the prelude instead of imported Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. Apply this change across the compiler. These functions were added to all preludes in Rust 1.80. r? ``@compiler-errors``
2025-03-09Rollup merge of #136968 - oli-obk:bye-bye, r=compiler-errorsMatthias Krüger-25/+5
Turn order dependent trait objects future incompat warning into a hard error fixes #56484 r? ``@ghost`` will FCP when we have a crater result
2025-03-09Do not register `Self: AutoTrait` when confirming auto traitMichael Goulet-15/+1
2025-03-07compiler: Use size_of from the prelude instead of importedThalia Archibald-1/+1
Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. These functions were added to all preludes in Rust 1.80.
2025-03-06Rollup merge of #137910 - compiler-errors:async-fn-goal-error, r=oli-obkMichael Goulet-1/+3
Improve error message for `AsyncFn` trait failure for RPIT Use a `WellFormedDerived` obligation cause to make sure we can turn an `AsyncFnKindHelper` trait goal into its parent `AsyncFn*` goal, then fix the logic for reporting `AsyncFn*` kind mismatches. Best reviewed without whitespace. Fixes #137905 r? oli-obk
2025-03-06Remove the `Option` part of range ends in the HIROli Scherer-1/+1
2025-03-06Avoid having to handle an `Option` in the type systemOli Scherer-6/+2
2025-03-05Rollup merge of #137728 - Darksonn:no-tuple-unsize, r=oli-obk许杰友 Jieyou Xu (Joe)-40/+2
Remove unsizing coercions for tuples See https://github.com/rust-lang/rust/issues/42877#issuecomment-2686010847 and below comments for justification. Tracking issue: #42877 Fixes: #135217
2025-03-05Rollup merge of #137633 - ↵许杰友 Jieyou Xu (Joe)-158/+58
compiler-errors:no-implied-bounds-hack-unless-bevy, r=lcnr Only use implied bounds hack if bevy, and use deeply normalize in implied bounds hack Consolidates the implied bounds computation mode into a single function, which deeply normalizes, and if it's in **compat** mode (for bevy), it extracts outlives bounds from the infcx. Previously, we were using the implied bounds compat mode in two cases: 1. During WF, if it detects `ParamSet` 2. EVERYWHERE ELSE (lol) -- e.g. borrowck, predicate entailment, etc. While I think this is fine, and the net effect was just that we emitted fewer diagnostics, it makes me uncomfortable that all crates were using the supposed "compat" code. Fixes #137767
2025-03-04Only use implied bounds hack if bevy, and use deeply normalize in implied ↵Michael Goulet-158/+58
bounds hack
2025-03-04mgca: Lower all const paths as `ConstArgKind::Path`Noah Lev-1/+7
When `#![feature(min_generic_const_args)]` is enabled, we now lower all const paths in generic arg position to `hir::ConstArgKind::Path`. We then lower assoc const paths to `ty::ConstKind::Unevaluated` since we can no longer use the anon const expression lowering machinery. In the process of implementing this, I factored out `hir_ty_lowering` code that is now shared between lowering assoc types and assoc consts. This PR also introduces a `#[type_const]` attribute for trait assoc consts that are allowed as const args. However, we still need to implement code to check that assoc const definitions satisfy `#[type_const]` if present (basically is it a const path or a monomorphic anon const).
2025-03-03Improve error message for AsyncFn trait failure for RPITMichael Goulet-1/+3
2025-03-01Rollup merge of #137822 - BoxyUwU:query_normalizer_docs, r=compiler-errorsMatthias Krüger-12/+9
Update query normalizer docs to not position it as the greatest pioneer in the space of normalization I don't think its true that we intend to replace all normalization with the query normalizer- its more likely that once the new solver is stable we can replace the query normalizer with normal normalization calls as the new solver caches much more than the old solver r? ``@compiler-errors``
2025-03-01Rollup merge of #137800 - BoxyUwU:param_env_docs, r=compiler-errorsMatthias Krüger-1/+1
Remove `ParamEnv::without_caller_bounds` This doesn't really do anything that `ParamEnv::empty` doesn't do nowadays as `ParamEnv` *only* stores caller bounds since other information has been moved out into `TypingMode` r? ```@compiler-errors``` ```@lcnr```
2025-03-01Rollup merge of #137776 - nnethercote:rustc_transmute-cleanups, r=jswrennMatthias Krüger-9/+4
Some `rustc_transmute` cleanups A number of small things that can be removed. r? ``@jswrenn``
2025-03-01Rollup merge of #137689 - compiler-errors:coroutine, r=lcnrMatthias Krüger-58/+21
Use `Binder<Vec<Ty>>` instead of `Vec<Binder<Ty>>` in both solvers for sized/auto traits/etc. It's more conceptually justified IMO, especially when binders get implications. r? lcnr
2025-02-28Update query normalizer docsBoxy-12/+9
2025-02-28reviewlcnr-3/+9
2025-02-28Remove `allow(unused_variables)` for `rustc_transmute`.Nicholas Nethercote-8/+3
This was hiding some genuine sins, including unused arguments in numerous functions/methods (incl. trait methods), and some unnecessary computation.
2025-02-28Remove `rustc_transmute`'s dependence on `rustc_infer`.Nicholas Nethercote-1/+1
`TransmuteTypeEnv` only needs a `TyCtxt`, not an `InferCtxt`.
2025-02-27Delete tuple unsizingAlice Ryhl-40/+2
2025-02-26Remove `ParamEnv::without_caller_bounds`Boxy-1/+1