Commit Graph

3793 Commits

Author SHA1 Message Date
Michael Goulet
357665dae9 Simplify fulfill_implication 2024-11-22 01:03:17 +00:00
Michael Goulet
0465f71d60 Stop being so bail-y in candidate assembly 2024-11-21 01:35:34 +00:00
Michael Goulet
06e66d78c3 Rip out built-in PointerLike impl 2024-11-20 16:13:57 +00:00
lcnr
002efeb72a additional TypingEnv cleanups 2024-11-19 21:36:23 +01:00
lcnr
4813fda2e6 rustdoc: yeet TypingEnv::from_param_env 2024-11-19 18:35:41 +01:00
lcnr
9cba14b95b use TypingEnv when no infcx is available
the behavior of the type system not only depends on the current
assumptions, but also the currentnphase of the compiler. This is
mostly necessary as we need to decide whether and how to reveal
opaque types. We track this via the `TypingMode`.
2024-11-18 10:38:56 +01:00
Boxy
6dad074907 Handle infer vars in anon consts on stable 2024-11-12 21:36:42 +00:00
Boxy
bea0148ac6 Consolidate type system const evaluation under traits::evaluate_const
mew
2024-11-12 02:54:03 +00:00
bors
c07aa1e171 Auto merge of #132625 - compiler-errors:cache-only-if-opaque, r=lcnr
Only disable cache if predicate has opaques within it

This is an alternative to https://github.com/rust-lang/rust/pull/132075.

This refines the check implemented in https://github.com/rust-lang/rust/pull/126024 to only disable the global cache if the predicate being considered has opaques in it. This is still theoretically unsound, since goals can indirectly rely on opaques in the defining scope, but we're much less likely to hit it.

It doesn't totally fix https://github.com/rust-lang/rust/issues/132064: for example, `lemmy` goes from 1:29 (on rust 1.81) to 9:53 (on nightly) to 4:07 (after this PR). But I think it's at least *more* sound than a total revert :/

r? lcnr
2024-11-06 21:22:14 +00:00
Michael Goulet
49153739fd Only disable cache if predicate has opaques within it 2024-11-05 17:38:26 +00:00
bors
096277e989 Auto merge of #132580 - compiler-errors:globs, r=Noratrieb
Remove unnecessary pub enum glob-imports from `rustc_middle::ty`

We used to have an idiom in the compiler where we'd prefix or suffix all the variants of an enum, for example `BoundRegionKind`, with something like `Br`, and then *glob-import* that enum variant directly.

`@noratrieb` brought this up, and I think that it's easier to read when we just use the normal style `EnumName::Variant`.

This PR is a bit large, but it's just naming.

The only somewhat opinionated change that this PR does is rename `BorrowKind::Imm` to `BorrowKind::Immutable` and same for the other variants. I think these enums are used sparingly enough that the extra length is fine.

r? `@noratrieb` or reassign
2024-11-05 08:30:56 +00:00
Matthias Krüger
c89a6cd0ad
Rollup merge of #132486 - compiler-errors:no-binder, r=lcnr
No need to instantiate binder in `confirm_async_closure_candidate`

Removes a FIXME that is redundant. No longer needed since #122267.
2024-11-04 18:12:45 +01:00
Michael Goulet
d458f850aa ty::BrK -> ty::BoundRegionKind::K 2024-11-04 04:45:52 +00:00
Michael Goulet
8e6af16192 Remove the trivial constkind imports 2024-11-04 04:45:51 +00:00
Michael Goulet
6b96103bf3 Rename the FIXMEs, remove a few that dont matter anymore 2024-11-03 18:59:41 +00:00
Jubilee Young
4046e3610c compiler: Replace rustc_target with _abi in _trait_selection 2024-11-02 20:31:47 -07:00
Michael Goulet
c10fe34fb9 No need to instantiate binder in confirm_async_closure_candidate 2024-11-02 03:10:37 +00:00
lcnr
dc750665ae normalization folders, yeet ParamEnv::reveal 2024-10-31 14:55:53 +01:00
lcnr
84295b917d traits::project: yeet ParamEnv::reveal 2024-10-31 12:06:19 +01:00
Jubilee
7b19508abe
Rollup merge of #132344 - compiler-errors:same-thing, r=lcnr
Merge `HostPolarity` and `BoundConstness`

They're basically the same thing, and I think `BoundConstness` is easier to use.

r? fee1-dead or reassign
2024-10-30 14:01:38 -07:00
Jubilee
847b6fe6b0
Rollup merge of #132246 - workingjubilee:campaign-on-irform, r=compiler-errors
Rename `rustc_abi::Abi` to `BackendRepr`

Remove the confabulation of `rustc_abi::Abi` with what "ABI" actually means by renaming it to `BackendRepr`, and rename `Abi::Aggregate` to `BackendRepr::Memory`. The type never actually represented how things are passed, as that has to have `PassMode` considered, at minimum, but rather it just is how we represented some things to the backend. This conflation arose because LLVM, the primary backend at the time, would lower certain IR forms using certain ABIs. Even that only somewhat was true, as it broke down when one ventured significantly afield of what is described by the System V AMD64 ABI either by using different architectures, ABI-modifying IR annotations, the same architecture **with different ISA extensions enabled**, or other... unexpected delights.

Unfortunately both names are still somewhat of a misnomer right now, as people have written code for years based on this misunderstanding. Still, their original names are even moreso, and for better or worse, this backend code hasn't received as much maintenance as the rest of the compiler, lately. Actually arriving at a correct end-state will simply require us to disentangle a lot of code in order to fix, much of it pointlessly repeated in several places. Thus this is not an "actual fix", just a way to deflect further misunderstandings.
2024-10-30 14:01:37 -07:00
Michael Goulet
802f3a78a6 Merge HostPolarity and BoundConstness 2024-10-30 16:23:16 +00:00
Jubilee Young
7086dd83cc compiler: rustc_abi::Abi => BackendRepr
The initial naming of "Abi" was an awful mistake, conveying wrong ideas
about how psABIs worked and even more about what the enum meant.
It was only meant to represent the way the value would be described to
a codegen backend as it was lowered to that intermediate representation.
It was never meant to mean anything about the actual psABI handling!
The conflation is because LLVM typically will associate a certain form
with a certain ABI, but even that does not hold when the special cases
that actually exist arise, plus the IR annotations that modify the ABI.

Reframe `rustc_abi::Abi` as the `BackendRepr` of the type, and rename
`BackendRepr::Aggregate` as `BackendRepr::Memory`. Unfortunately, due to
the persistent misunderstandings, this too is now incorrect:
- Scattered ABI-relevant code is entangled with BackendRepr
- We do not always pre-compute a correct BackendRepr that reflects how
  we "actually" want this value to be handled, so we leave the backend
  interface to also inject various special-cases here
- In some cases `BackendRepr::Memory` is a "real" aggregate, but in
  others it is in fact using memory, and in some cases it is a scalar!

Our rustc-to-backend lowering code handles this sort of thing right now.
That will eventually be addressed by lifting duplicated lowering code
to either rustc_codegen_ssa or rustc_target as appropriate.
2024-10-29 14:56:00 -07:00
lcnr
524a22e790 rebase 2024-10-29 17:07:32 +01:00
lcnr
f51ec110a7 TypingMode 🤔 2024-10-29 17:01:24 +01:00
Michael Goulet
8b7b8e5f56 Hack out effects support for old solver 2024-10-28 21:42:14 +00:00
Michael Goulet
7f54b9ecef Remove ObligationCause::span() method 2024-10-27 23:54:06 +00:00
Ralf Jung
8849ac6042 tcx.is_const_fn doesn't work the way it is described, remove it
Then we can rename the _raw functions to drop their suffix, and instead
explicitly use is_stable_const_fn for the few cases where that is really what
you want.
2024-10-25 20:52:39 +02:00
bors
1d4a7670d4 Auto merge of #131985 - compiler-errors:const-pred, r=fee1-dead
Represent trait constness as a distinct predicate

cc `@rust-lang/project-const-traits`
r? `@ghost` for now

Also mirrored everything that is written below on this hackmd here: https://hackmd.io/`@compiler-errors/r12zoixg1l`

# Tl;dr:

* This PR removes the bulk of the old effect desugaring.
* This PR reimplements most of the effect desugaring as a new predicate and set of a couple queries. I believe it majorly simplifies the implementation and allows us to move forward more easily on its implementation.

I'm putting this up both as a request for comments and a vibe-check, but also as a legitimate implementation that I'd like to see land (though no rush of course on that last part).

## Background

### Early days

Once upon a time, we represented trait constness in the param-env and in `TraitPredicate`. This was very difficult to implement correctly; it had bugs and was also incomplete; I don't think this was anyone's fault though, it was just the limit of experimental knowledge we had at that point.

Dealing with `~const` within predicates themselves meant dealing with constness all throughout the trait solver. This was difficult to keep track of, and afaict was not handled well with all the corners of candidate assembly.

Specifically, we had to (in various places) remap constness according to the param-env constness:

574b64a97f/compiler/rustc_trait_selection/src/traits/select/mod.rs (L1498)

This was annoying and manual and also error prone.

### Beginning of the effects desugaring

Later on, #113210 reimplemented a new desugaring for const traits via a `<const HOST: bool>` predicate. This essentially "reified" the const checking and separated it from any of the remapping or separate tracking in param-envs. For example, if I was in a const-if-const environment, but I wanted to call a trait that was non-const, this reification would turn the constness mismatch into a simple *type* mismatch of the effect parameter.

While this was a monumental step towards straightening out const trait checking in the trait system, it had its own issues, since that meant that the constness of a trait (or any item within it, like an associated type) was *early-bound*. This essentially meant that `<T as Trait>::Assoc` was *distinct* from `<T as ~const Trait>::Assoc`, which was bad.

### Associated-type bound based effects desugaring

After this, #120639 implemented a new effects desugaring. This used an associated type to more clearly represent the fact that the constness is not an input parameter of a trait, but a property that could be computed of a impl. The write-up linked in that PR explains it better than I could.

However, I feel like it really reached the limits of what can comfortably be expressed in terms of associated type and trait calculus. Also, `<const HOST: bool>` remains a synthetic const parameter, which is observable in nested items like RPITs and closures, and comes with tons of its own hacks in the astconv and middle layer.

For example, there are pieces of unintuitive code that are needed to represent semantics like elaboration, and eventually will be needed to make error reporting intuitive, and hopefully in the future assist us in implementing built-in traits (eventually we'll want something like `~const Fn` trait bounds!).

elaboration hack: 8069f8d17a/compiler/rustc_type_ir/src/elaborate.rs (L133-L195)

trait bound remapping hack for diagnostics: 8069f8d17a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs (L2370-L2413)

I want to be clear that I don't think this is a issue of implementation quality or anything like that; I think it's simply a very clear sign that we're using types and traits in a way that they're not fundamentally supposed to be used, especially given that constness deserves to be represented as a first-class concept.

### What now?

This PR implements a new desugaring for const traits. Specifically, it introduces a `HostEffect` predicate to represent the obligation an impl is const, rather than using associated type bounds and the compat trait that exists for effects today.

### `HostEffect` predicate

A `HostEffect` clause has two parts -- the `TraitRef` we're trying to prove, and a `HostPolarity::{Maybe, Const}`.

`HostPolarity::Const` corresponds to `T: const Trait` bounds, which must *always* be proven as const, and which can be written in any context. These are lowered directly into the predicates of an item, since they're not "context-specific".

On the other hand, `HostPolarity::Maybe` corresponds to `T: ~const Trait` bounds which must only exist in a conditionally-const context like a method in a `#[const_trait]`, or a `const fn` free function. We do not lower these immediately into the predicates of an item; instead, we collect them into a new query called the **`const_conditions`**. These are the set of trait refs that we need to prove have const implementations for an item to be const.

Notably, they're represented as bare (poly) trait refs because they are meant to be paired back together with a `HostPolarity` when they're being registered in typeck (see next section).

For example, given:

```rust
const fn foo<T: ~const A + const B>() {}
```

`foo`'s const conditions would contain `T: A`, but not `T: B`. On the flip side, foo's predicates (`predicates_of`) query would contain `HostEffect(T: B, HostPolarity::Const)` but not `HostEffect(T: A, HostPolarity::Maybe)` since we don't need to prove that predicate in a non-const environment (and it's not even the right predicate to prove in an unconditionally const environment).

### Type checking const bodies

When type checking bodies in HIR, when we encounter a call expression, we additionally register the callee item's const conditions with the `HostPolarity` from the body we're typechecking (`Const` for unconditionally const things like `const`/`static` items, and `Maybe` for conditionally const things like const fns; and we don't register `HostPolarity` predicates for non-const bodies).

When type-checking a conditionally const body, we augment its param-env with `HostEffect(..., Maybe)` predicates.

### Checking that const impls are WF

We extend the logic in `compare_method_predicate_entailment` to also check the const-conditions of the impl method, to make sure that we error for:

```rust
#[const_trait] Bar {}
#[const_trait] trait Foo {
    fn method<T: Bar>();
}

impl Foo for () {
    fn method<T: ~const Bar>() {} // stronger assumption!
}
```

We also extend the WF check for impls to register the const conditions of the trait that is being implemented. This is to make sure we error for:

```rust
#[const_trait] trait Bar {}
#[const_trait] trait Foo<T> where T: ~const Bar {}

impl<T> const Foo<T> for () {}
//~^ `T: ~const Bar` is missing!
```

### Proving a `HostEffect` predicate

We have several ways of proving a `HostEffect` predicate:

1. Matching a `HostEffect` predicate from the param-env
2. From an impl - we do impl selection very similar to confirming a trait goal, except we filter for only const impls, and we additionally register the impl's const conditions (i.e. the impl's `~const` where clauses).

Later I expect that we will add more built-in implementations for things like `Fn`.

## What next?

After this PR, I'd like to split out the work more so it can proceed in parallel and probably amongst others that are not me.

* Register `HostEffect` goal for places in HIR typeck that correspond to call terminators, like autoderef.
* Make traits in libstd const again.
    * Probably need to impl host effect preds in old solver.
* Implement built-in `HostEffect` rules for traits like `Fn`.
* Rip out const checking from MIR altogether.

## So what?

This ends up being super convenient basically everywhere in the compiler. Due to the design of the new trait solver, we end up having an almost parallel structure to the existing trait and projection predicates for assembling `HostEffect` predicates; adding new candidates and especially new built-in implementations is now basically trivial, and it's quite straightforward to understand the confirmation logic for these predicates.

Same with diagnostics reporting; since we have predicates which represent the obligation to prove an impl is const, we can simplify and make these diagnostics richer without having to write a ton of logic to intercept and rewrite the existing `Compat` trait errors.

Finally, it gives us a much more straightforward path for supporting the const effect on the old trait solver. I'm personally quite passionate about getting const trait support into the hands of users without having to wait until the new solver lands[^1], so I think after this PR lands we can begin to gauge how difficult it would be to implement constness in the old trait solver too. This PR will not do this yet.

[^1]: Though this is not a prerequisite or by any means the only justification for this PR.
2024-10-24 17:33:42 +00:00
Michael Goulet
cde29b9ec9 Implement const effect predicate in new solver 2024-10-24 09:46:36 +00:00
Michael Goulet
a16d491054 Remove associated type based effects logic 2024-10-24 09:46:36 +00:00
Michael Goulet
d8dc31fd3d Consider param-env candidates even if they have errors 2024-10-24 01:48:44 +00:00
Ralf Jung
ad3991d303 nightly feature tracking: get rid of the per-feature bool fields 2024-10-23 09:14:41 +01:00
bors
814df6e50e Auto merge of #131840 - compiler-errors:impossible-maybe, r=lcnr
Dont consider predicates that may hold as impossible in `is_impossible_associated_item`

Use infer vars to account for ambiguities when considering if methods are impossible to instantiate for a given self type. Also while we're at it, let's use the new trait solver instead of `evaluate` since this is used in rustdoc.

r? lcnr
Fixes #131839
2024-10-21 22:58:44 +00:00
lcnr
b64b25b99e normalizes-to disable infer var check 2024-10-21 16:25:42 +02:00
bors
93742bd782 Auto merge of #131988 - matthiaskrgr:rollup-tx173wn, r=matthiaskrgr
Rollup of 4 pull requests

Successful merges:

 - #126588 (Added more scenarios where comma to be removed in the function arg)
 - #131728 (bootstrap: extract builder cargo to its own module)
 - #131968 (Rip out old effects var handling code from traits)
 - #131981 (Remove the `BoundConstness::NotConst` variant)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-10-21 06:13:34 +00:00
Michael Goulet
6f6f91ab82 Rip out old effects var handling code from traits 2024-10-20 13:40:22 +00:00
Michael Goulet
9453d2cfeb Fix transmute goal 2024-10-19 18:07:35 +00:00
Michael Goulet
38bbcc001e Rename normalize to normalize_internal, remove unnecessary usages 2024-10-19 18:07:35 +00:00
许杰友 Jieyou Xu (Joe)
765e8c75b0
Rollup merge of #131864 - lrh2000:upcast_reorder, r=WaffleLapkin
Never emit `vptr` for empty/auto traits

Emiting `vptr`s for empty/auto traits is unnecessary (#114942) and causes unsoundness in `trait_upcasting` (#131813). This PR should ensure that we never emit vtables for such traits. See the linked issues for more details.

I'm not sure if I can add tests for the vtable layout. So this PR only adds tests for the soundness hole (i.e., the segmentation fault will disappear after this PR).

Fixes #114942
Fixes #131813

Cc #65991 (tracking issue for `trait_upcasting`)

r? `@WaffleLapkin`  (per https://github.com/rust-lang/rust/issues/131813#issuecomment-2419969745)
2024-10-18 14:52:25 +01:00
Ruihan Li
781bff0499 Never emit vptr for empty/auto traits 2024-10-18 12:34:56 +08:00
Michael Goulet
e3800a1a04 Allow dropping dyn principal 2024-10-17 20:43:31 +02:00
Michael Goulet
8ff8f78e4c Dont consider predicates that may hold as impossible in is_impossible_associated_item 2024-10-17 12:32:31 -04:00
lcnr
3360c1773a move defining_opaque_types out of Canonical 2024-10-17 10:22:52 +02:00
lcnr
f3ce557fcd DropckOutlives to rustc_middle 2024-10-17 09:53:27 +02:00
lcnr
401f9b4e0a ImpliedOutlivesBounds to rustc_middle 2024-10-17 09:53:27 +02:00
bors
9618da7c99 Auto merge of #131422 - GnomedDev:smallvec-predicate-obligations, r=compiler-errors
Use `ThinVec` for PredicateObligation storage

~~I noticed while profiling clippy on a project that a large amount of time is being spent allocating `Vec`s for `PredicateObligation`, and the `Vec`s are often quite small. This is an attempt to optimise this by using SmallVec to avoid heap allocations for these common small Vecs.~~

This PR turns all the `Vec<PredicateObligation>` into a single type alias while avoiding referring to `Vec` around it, then swaps the type over to `ThinVec<PredicateObligation>` and fixes the fallout. This also contains an implementation of `ThinVec::extract_if`, copied from `Vec::extract_if` and currently being upstreamed to https://github.com/Gankra/thin-vec/pull/66.

This leads to a small (0.2-0.7%) performance gain in the latest perf run.
2024-10-16 04:06:14 +00:00
bors
a0c2aba29a Auto merge of #130654 - lcnr:stabilize-coherence-again, r=compiler-errors
stabilize `-Znext-solver=coherence` again

r? `@compiler-errors`

---

This PR stabilizes the use of the next generation trait solver in coherence checking by enabling `-Znext-solver=coherence` by default. More specifically its use in the *implicit negative overlap check*. The tracking issue for this is https://github.com/rust-lang/rust/issues/114862. Closes #114862.

This is a direct copy of #121848 which has been reverted due to a hang in `nalgebra`: #130056. This hang should have been fixed by #130617 and #130821. See the added section in the stabilization report containing user facing changes merged since the original FCP.

## Background

### The next generation trait solver

The new solver lives in [`rustc_trait_selection::solve`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_trait_selection/src/solve/mod.rs) and is intended to replace the existing *evaluate*, *fulfill*, and *project* implementation. It also has a wider impact on the rest of the type system, for example by changing our approach to handling associated types.

For a more detailed explanation of the new trait solver, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/solve/trait-solving.html). This does not stabilize the current behavior of the new trait solver, only the behavior impacting the implicit negative overlap check. There are many areas in the new solver which are not yet finalized. We are confident that their final design will not conflict with the user-facing behavior observable via coherence. More on that further down.

Please check out [the chapter](https://rustc-dev-guide.rust-lang.org/solve/significant-changes.html) summarizing the most significant changes between the existing and new implementations.

### Coherence and the implicit negative overlap check

Coherence checking detects any overlapping impls. Overlapping trait impls always error while overlapping inherent impls result in an error if they have methods with the same name. Coherence also results in an error if any other impls could exist, even if they are currently unknown. This affects impls which may get added to upstream crates in a backwards compatible way and impls from downstream crates.

Coherence failing to detect overlap is generally considered to be unsound, even if it is difficult to actually get runtime UB this way. It is quite easy to get ICEs due to bugs in coherence.

It currently consists of two checks:

The [orphan check] validates that impls do not overlap with other impls we do not know about: either because they may be defined in a sibling crate, or because an upstream crate is allowed to add it without being considered a breaking change.

The [overlap check] validates that impls do not overlap with other impls we know about. This is done as follows:
- Instantiate the generic parameters of both impls with inference variables
- Equate the `TraitRef`s of both impls. If it fails there is no overlap.
- [implicit negative]: Check whether any of the instantiated `where`-bounds of one of the impls definitely do not hold when using the constraints from the previous step. If a `where`-bound does not hold, there is no overlap.
- *explicit negative (still unstable, ignored going forward)*: Check whether the any negated `where`-bounds can be proven, e.g. a `&mut u32: Clone` bound definitely does not hold as an explicit `impl<T> !Clone for &mut T` exists.

The overlap check has to *prove that unifying the impls does not succeed*. This means that **incorrectly getting a type error during coherence is unsound** as it would allow impls to overlap: coherence has to be *complete*.

Completeness means that we never incorrectly error. This means that during coherence we must only add inference constraints if they are definitely necessary. During ordinary type checking [this does not hold](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=01d93b592bd9036ac96071cbf1d624a9), so the trait solver has to behave differently, depending on whether we're in coherence or not.

The implicit negative check only considers goals to "definitely not hold" if they could not be implemented downstream, by a sibling, or upstream in a backwards compatible way. If the goal is is "unknowable" as it may get added in another crate, we add an ambiguous candidate: [source](bea5bebf3d/compiler/rustc_trait_selection/src/solve/assembly/mod.rs (L858-L883)).

[orphan check]: fd80c02c16/compiler/rustc_trait_selection/src/traits/coherence.rs (L566-L579)
[overlap check]: fd80c02c16/compiler/rustc_trait_selection/src/traits/coherence.rs (L92-L98)
[implicit negative]: fd80c02c16/compiler/rustc_trait_selection/src/traits/coherence.rs (L223-L281)

## Motivation

Replacing the existing solver in coherence fixes soundness bugs by removing sources of incompleteness in the type system. The new solver separately strengthens coherence, resulting in more impls being disjoint and passing the coherence check. The concrete changes will be elaborated further down. We believe the stabilization to reduce the likelihood of future bugs in coherence as the new implementation is easier to understand and reason about.

It allows us to remove the support for coherence and implicit-negative reasoning in the old solver, allowing us to remove some code and simplifying the old trait solver. We will only remove the old solver support once this stabilization has reached stable to make sure we're able to quickly revert in case any unexpected issues are detected before then.

Stabilizing the use of the next-generation trait solver expresses our confidence that its current behavior is intended and our work towards enabling its use everywhere will not require any breaking changes to the areas used by coherence checking. We are also confident that we will be able to replace the existing solver everywhere, as maintaining two separate systems adds a significant maintainance burden.

## User-facing impact and reasoning

### Breakage due to improved handling of associated types

The new solver fixes multiple issues related to associated types. As these issues caused coherence to consider more types distinct, fixing them results in more overlap errors. This is therefore a breaking change.

#### Structurally relating aliases containing bound vars

Fixes https://github.com/rust-lang/rust/issues/102048. In the existing solver relating ambiguous projections containing bound variables is structural. This is *incomplete* and allows overlapping impls. These was mostly not exploitable as the same issue also caused impls to not apply when trying to use them. The new solver defers alias-relating to a nested goal, fixing this issue:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Trait {}

trait Project {
    type Assoc<'a>;
}

impl Project for u32 {
    type Assoc<'a> = &'a u32;
}

// Eagerly normalizing `<?infer as Project>::Assoc<'a>` is ambiguous,
// so the old solver ended up structurally relating
//
//     (?infer, for<'a> fn(<?infer as Project>::Assoc<'a>))
//
// with
//
//     ((u32, fn(&'a u32)))
//
// Equating `&'a u32` with `<u32 as Project>::Assoc<'a>` failed, even
// though these types are equal modulo normalization.
impl<T: Project> Trait for (T, for<'a> fn(<T as Project>::Assoc<'a>)) {}

impl<'a> Trait for (u32, fn(&'a u32)) {}
//[next]~^ ERROR conflicting implementations of trait `Trait` for type `(u32, for<'a> fn(&'a u32))`
```

A crater run did not discover any breakage due to this change.

#### Unknowable candidates for higher ranked trait goals

This avoids an unsoundness by attempting to normalize in `trait_ref_is_knowable`, fixing https://github.com/rust-lang/rust/issues/114061. This is a side-effect of supporting lazy normalization, as that forces us to attempt to normalize when checking whether a `TraitRef` is knowable: [source](47dd709bed/compiler/rustc_trait_selection/src/solve/assembly/mod.rs (L754-L764)).

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait IsUnit {}
impl IsUnit for () {}

pub trait WithAssoc<'a> {
    type Assoc;
}

// We considered `for<'a> <T as WithAssoc<'a>>::Assoc: IsUnit`
// to be knowable, even though the projection is ambiguous.
pub trait Trait {}
impl<T> Trait for T
where
    T: 'static,
    for<'a> T: WithAssoc<'a>,
    for<'a> <T as WithAssoc<'a>>::Assoc: IsUnit,
{
}
impl<T> Trait for Box<T> {}
//[next]~^ ERROR conflicting implementations of trait `Trait`
```
The two impls of `Trait` overlap given the following downstream crate:
```rust
use dep::*;
struct Local;
impl WithAssoc<'_> for Box<Local> {
    type Assoc = ();
}
```

There a similar coherence unsoundness caused by our handling of aliases which is fixed separately in https://github.com/rust-lang/rust/pull/117164.

This change breaks the [`derive-visitor`](https://crates.io/crates/derive-visitor) crate. I have opened an issue in that repo: nikis05/derive-visitor#16.

### Evaluating goals to a fixpoint and applying inference constraints

In the old implementation of the implicit-negative check, each obligation is [checked separately without applying its inference constraints](bea5bebf3d/compiler/rustc_trait_selection/src/traits/coherence.rs (L323-L338)). The new solver instead [uses a `FulfillmentCtxt`](bea5bebf3d/compiler/rustc_trait_selection/src/traits/coherence.rs (L315-L321)) for this, which evaluates all obligations in a loop until there's no further inference progress.

This is necessary for backwards compatibility as we do not eagerly normalize with the new solver, resulting in constraints from normalization to only get applied by evaluating a separate obligation. This also allows more code to compile:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Mirror {
    type Assoc;
}
impl<T> Mirror for T {
    type Assoc = T;
}

trait Foo {}
trait Bar {}

// The self type starts out as `?0` but is constrained to `()`
// due to the where-clause below. Because `(): Bar` is known to
// not hold, we can prove the impls disjoint.
impl<T> Foo for T where (): Mirror<Assoc = T> {}
//[current]~^ ERROR conflicting implementations of trait `Foo` for type `()`
impl<T> Foo for T where T: Bar {}

fn main() {}
```
The old solver does not run nested goals to a fixpoint in evaluation. The new solver does do so, strengthening inference and improving the overlap check:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Foo {}
impl<T> Foo for (u8, T, T) {}
trait NotU8 {}
trait Bar {}
impl<T, U: NotU8> Bar for (T, T, U) {}

trait NeedsFixpoint {}
impl<T: Foo + Bar> NeedsFixpoint for T {}
impl NeedsFixpoint for (u8, u8, u8) {}

trait Overlap {}
impl<T: NeedsFixpoint> Overlap for T {}
impl<T, U: NotU8, V> Overlap for (T, U, V) {}
//[current]~^ ERROR conflicting implementations of trait `Foo`
```

### Breakage due to removal of incomplete candidate preference

Fixes #107887. In the old solver we incompletely prefer the builtin trait object impl over user defined impls. This can break inference guidance, inferring `?x` in `dyn Trait<u32>: Trait<?x>` to `u32`, even if an explicit impl of `Trait<u64>` also exists.

This caused coherence to incorrectly allow overlapping impls, resulting in ICEs and a theoretical unsoundness. See https://github.com/rust-lang/rust/issues/107887#issuecomment-1997261676. This compiles on stable but results in an overlap error with `-Znext-solver=coherence`:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
struct W<T: ?Sized>(*const T);

trait Trait<T: ?Sized> {
    type Assoc;
}

// This would trigger the check for overlap between automatic and custom impl.
// They actually don't overlap so an impl like this should remain possible
// forever.
//
// impl Trait<u64> for dyn Trait<u32> {}
trait Indirect {}
impl Indirect for dyn Trait<u32, Assoc = ()> {}
impl<T: Indirect + ?Sized> Trait<u64> for T {
    type Assoc = ();
}

// Incomplete impl where `dyn Trait<u32>: Trait<_>` does not hold, but
// `dyn Trait<u32>: Trait<u64>` does.
trait EvaluateHack<U: ?Sized> {}
impl<T: ?Sized, U: ?Sized> EvaluateHack<W<U>> for T
where
    T: Trait<U, Assoc = ()>, // incompletely constrains `_` to `u32`
    U: IsU64,
    T: Trait<U, Assoc = ()>, // incompletely constrains `_` to `u32`
{
}

trait IsU64 {}
impl IsU64 for u64 {}

trait Overlap<U: ?Sized> {
    type Assoc: Default;
}
impl<T: ?Sized + EvaluateHack<W<U>>, U: ?Sized> Overlap<U> for T {
    type Assoc = Box<u32>;
}
impl<U: ?Sized> Overlap<U> for dyn Trait<u32, Assoc = ()> {
//[next]~^ ERROR conflicting implementations of trait `Overlap<_>`
    type Assoc = usize;
}
```

### Considering region outlives bounds in the `leak_check`

For details on the `leak_check`, see the FCP proposal #119820.[^leak_check]

[^leak_check]: which should get moved to the dev-guide :3

In both coherence and during candidate selection, the `leak_check` relies on the region constraints added in `evaluate`. It therefore currently does not register outlives obligations: [source](ccb1415eac/compiler/rustc_trait_selection/src/traits/select/mod.rs (L792-L810)). This was likely done as a performance optimization without considering its impact on the `leak_check`. This is the case as in the old solver, *evaluatation* and *fulfillment* are split, with evaluation being responsible for candidate selection and fulfillment actually registering all the constraints.

This split does not exist with the new solver. The `leak_check` can therefore eagerly detect errors caused by region outlives obligations. This improves both coherence itself and candidate selection:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait LeakErr<'a, 'b> {}
// Using this impl adds an `'b: 'a` bound which results
// in a higher-ranked region error. This bound has been
// previously ignored but is now considered.
impl<'a, 'b: 'a> LeakErr<'a, 'b> for () {}

trait NoOverlapDir<'a> {}
impl<'a, T: for<'b> LeakErr<'a, 'b>> NoOverlapDir<'a> for T {}
impl<'a> NoOverlapDir<'a> for () {}
//[current]~^ ERROR conflicting implementations of trait `NoOverlapDir<'_>`

// --------------------------------------

// necessary to avoid coherence unknowable candidates
struct W<T>(T);

trait GuidesSelection<'a, U> {}
impl<'a, T: for<'b> LeakErr<'a, 'b>> GuidesSelection<'a, W<u32>> for T {}
impl<'a, T> GuidesSelection<'a, W<u8>> for T {}

trait NotImplementedByU8 {}
trait NoOverlapInd<'a, U> {}
impl<'a, T: GuidesSelection<'a, W<U>>, U> NoOverlapInd<'a, U> for T {}
impl<'a, U: NotImplementedByU8> NoOverlapInd<'a, U> for () {}
//[current]~^ conflicting implementations of trait `NoOverlapInd<'_, _>`
```

### Removal of `fn match_fresh_trait_refs`

The old solver tries to [eagerly detect unbounded recursion](b14fd2359f/compiler/rustc_trait_selection/src/traits/select/mod.rs (L1196-L1211)), forcing the affected goals to be ambiguous. This check is only an approximation and has not been added to the new solver.

The check is not necessary in the new solver and it would be problematic for caching. As it depends on all goals currently on the stack, using a global cache entry would have to always make sure that doing so does not circumvent this check.

This changes some goals to error - or succeed - instead of failing with ambiguity. This allows more code to compile:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence

// Need to use this local wrapper for the impls to be fully
// knowable as unknowable candidate result in ambiguity.
struct Local<T>(T);

trait Trait<U> {}
// This impl does not hold, but is ambiguous in the old
// solver due to its overflow approximation.
impl<U> Trait<U> for Local<u32> where Local<u16>: Trait<U> {}
// This impl holds.
impl Trait<Local<()>> for Local<u8> {}

// In the old solver, `Local<?t>: Trait<Local<?u>>` is ambiguous,
// resulting in `Local<?u>: NoImpl`, also being ambiguous.
//
// In the new solver the first impl does not apply, constraining
// `?u` to `Local<()>`, causing `Local<()>: NoImpl` to error.
trait Indirect<T> {}
impl<T, U> Indirect<U> for T
where
    T: Trait<U>,
    U: NoImpl
{}

// Not implemented for `Local<()>`
trait NoImpl {}
impl NoImpl for Local<u8> {}
impl NoImpl for Local<u16> {}

// `Local<?t>: Indirect<Local<?u>>` cannot hold, so
// these impls do not overlap.
trait NoOverlap<U> {}
impl<T: Indirect<U>, U> NoOverlap<U> for T {}
impl<T, U> NoOverlap<Local<U>> for Local<T> {}
//~^ ERROR conflicting implementations of trait `NoOverlap<Local<_>>`
```

### Non-fatal overflow

The old solver immediately emits a fatal error when hitting the recursion limit. The new solver instead returns overflow. This both allows more code to compile and is results in performance and potential future compatability issues.

Non-fatal overflow is generally desirable. With fatal overflow, changing the order in which we evaluate nested goals easily causes breakage if we have goal which errors and one which overflows. It is also required to prevent breakage due to the removal of `fn match_fresh_trait_refs`, e.g. [in `typenum`](https://github.com/rust-lang/trait-system-refactor-initiative/issues/73).

#### Enabling more code to compile

In the below example, the old solver first tried to prove an overflowing goal, resulting in a fatal error. The new solver instead returns ambiguity due to overflow for that goal, causing the implicit negative overlap check to succeed as `Box<u32>: NotImplemented` does not hold.
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
//[current] ERROR overflow evaluating the requirement

trait Indirect<T> {}
impl<T: Overflow<()>> Indirect<T> for () {}

trait Overflow<U> {}
impl<T, U> Overflow<U> for Box<T>
where
    U: Indirect<Box<Box<T>>>,
{}

trait NotImplemented {}

trait Trait<U> {}
impl<T, U> Trait<U> for T
where
    // T: NotImplemented, // causes old solver to succeed
    U: Indirect<T>,
    T: NotImplemented,
{}

impl Trait<()> for Box<u32> {}
```

#### Avoiding hangs with non-fatal overflow

Simply returning ambiguity when reaching the recursion limit can very easily result in hangs, e.g.
```rust
trait Recur {}
impl<T, U> Recur for ((T, U), (U, T))
where
    (T, U): Recur,
    (U, T): Recur,
{}

trait NotImplemented {}
impl<T: NotImplemented> Recur for T {}
```
This can happen quite frequently as it's easy to have exponential blowup due to multiple nested goals at each step. As the trait solver is depth-first, this immediately caused a fatal overflow error in the old solver. In the new solver we have to handle the whole proof tree instead, which can very easily hang.

To avoid this we restrict the recursion depth after hitting the recursion limit for the first time. We also **ignore all inference constraints from goals resulting in overflow**. This is mostly backwards compatible as any overflow in the old solver resulted in a fatal error.

### sidenote about normalization

We return ambiguous nested goals of `NormalizesTo` goals to the caller and ignore their impact when computing the `Certainty` of the current goal. See the [normalization chapter](https://rustc-dev-guide.rust-lang.org/solve/normalization.html) for more details.This means we apply constraints resulting from other nested goals and from equating the impl header when normalizing, even if a nested goal results in overflow. This is necessary to avoid breaking the following example:
```rust
trait Trait {
    type Assoc;
}

struct W<T: ?Sized>(*mut T);
impl<T: ?Sized> Trait for W<W<T>>
where
    W<T>: Trait,
{
    type Assoc = ();
}

// `W<?t>: Trait<Assoc = u32>` does not hold as
// `Assoc` gets normalized to `()`. However, proving
// the where-bounds of the impl results in overflow.
//
// For this to continue to compile we must not discard
// constraints from normalizing associated types.
trait NoOverlap {}
impl<T: Trait<Assoc = u32>> NoOverlap for T {}
impl<T: ?Sized> NoOverlap for W<T> {}
```

#### Future compatability concerns

Non-fatal overflow results in some unfortunate future compatability concerns. Changing the approach to avoid more hangs by more strongly penalizing overflow can cause breakage as we either drop constraints or ignore candidates necessary to successfully compile. Weakening the overflow penalities instead allows more code to compile and strengthens inference while potentially causing more code to hang.

While the current approach is not perfect, we believe it to be good enough. We believe it to apply the necessary inference constraints to avoid breakage and expect there to not be any desirable patterns broken by our current penalities. Similarly we believe the current constraints to avoid most accidental hangs. Ignoring constraints of overflowing goals is especially useful, as it may allow major future optimizations to our overflow handling. See [this summary](https://hackmd.io/ATf4hN0NRY-w2LIVgeFsVg) and the linked documents in case you want to know more.

### changes to performance

In general, trait solving during coherence checking is not significant for performance. Enabling the next-generation trait solver in coherence does not impact our compile time benchmarks. We are still unable to compile the benchmark suite when fully enabling the new trait solver.

There are rare cases where the new solver has significantly worse performance due to non-fatal overflow, its reliance on fixpoint algorithms and the removal of the `fn match_fresh_trait_refs` approximation. We encountered such issues in [`typenum`](https://crates.io/crates/typenum) and believe it should be [pretty much as bad as it can get](https://github.com/rust-lang/trait-system-refactor-initiative/issues/73).

Due to an improved structure and far better caching, we believe that there is a lot of room for improvement and that the new solver will outperform the existing implementation in nearly all cases, sometimes significantly. We have not yet spent any time micro-optimizing the implementation and have many unimplemented major improvements, such as fast-paths for trivial goals.

### Unstable features

#### Unsupported unstable features

The new solver currently does not support all unstable features, most notably `#![feature(generic_const_exprs)]`, `#![feature(associated_const_equality)]` and `#![feature(adt_const_params)]` are not yet fully supported in the new solver. We are confident that supporting them is possible, but did not consider this to be a priority. This stabilization introduces new ICE when using these features in impl headers.

#### fixes to `#![feature(specialization)]`

- fixes #105782
- fixes #118987

#### fixes to `#![feature(type_alias_impl_trait)]`

- fixes #119272
- https://github.com/rust-lang/rust/issues/105787#issuecomment-1750112388
- fixes #124207

### Important changes since the original FCP

https://github.com/rust-lang/rust/pull/127574 changes the coherence unknowable candidate to only apply if all the super trait bounds may hold. This allows more code to compile and fixes a regression in `pyella`

https://github.com/rust-lang/rust/pull/130617 bails with ambiguity if the query response would contain too many non-region inference variables. This should only be triggered in case the result contains a lot of ambiguous aliases in which case further constraining the goal should resolve this.

https://github.com/rust-lang/rust/pull/130821 adds caching to a lot of type folders, which is necessary to handle exponentially large types and handles the hang in `nalgebra` together with #130617.

## This does not stabilize the whole solver

While this stabilizes the use of the new solver in coherence checking, there are many parts of the solver which will remain fully unstable. We may still adapt these areas while working towards stabilizing the new solver everywhere. We are confident that we are able to do so without negatively impacting coherence.

### goals with a non-empty `ParamEnv`

Coherence always uses an empty environment. We therefore do not depend on the behavior of `AliasBound` and `ParamEnv` candidates. We only stabilizes the behavior of user-defined and builtin implementations of traits. There are still many open questions there.

### opaque types in the defining scope

The handling of opaque types - `impl Trait` - in both the new and old solver is still not fully figured out. Luckily this can be ignored for now. While opaque types are reachable during coherence checking by using `impl_trait_in_associated_types`, the behavior during coherence is separate and self-contained. The old and new solver fully agree here.

### normalization is hard

This stabilizes that we equate associated types involving bound variables using deferred-alias-equality. We also stop eagerly normalizing in coherence, which should not have any user-facing impact.

We do not stabilize the normalization behavior outside of coherence, e.g. we currently deeply normalize all types during writeback with the new solver. This may change going forward

### how to replace `select` from the old solver

We sometimes depend on getting a single `impl` for a given trait bound, e.g. when resolving a concrete method for codegen/CTFE. We do not depend on this during coherence, so the exact approach here can still be freely changed going forward.

## Acknowledgements

This work would not have been possible without `@compiler-errors.` He implemented large chunks of the solver himself but also and did a lot of testing and experimentation, eagerly discovering multiple issues which had a significant impact on our approach. `@BoxyUwU` has also done some amazing work on the solver. Thank you for the endless hours of discussion resulting in the current approach. Especially the way aliases are handled has gone through multiple revisions to get to its current state.

There were also many contributions from - and discussions with - other members of the community and the rest of `@rust-lang/types.` This solver builds upon previous improvements to the compiler, as well as lessons learned from `chalk` and `a-mir-formality`. Getting to this point  would not have been possible without that and I am incredibly thankful to everyone involved. See the [list of relevant PRs](https://github.com/rust-lang/rust/pulls?q=is%3Apr+is%3Amerged+label%3AWG-trait-system-refactor+-label%3Arollup+closed%3A%3C2024-03-22+).
2024-10-15 14:21:34 +00:00
lcnr
1a9d2d82a5 stabilize -Znext-solver=coherence 2024-10-15 13:11:00 +02:00
Michael Goulet
7500e09b8b Move trait bound modifiers into hir::PolyTraitRef 2024-10-14 09:20:38 -04:00
GnomedDev
8de8f46f78 Swap PredicateObligation to ThinVec 2024-10-12 15:17:16 +01:00
GnomedDev
7ec06b0d1d Swap Vec<PredicateObligation> to type alias 2024-10-12 15:17:08 +01:00
Matthias Krüger
fa3dff3e24
Rollup merge of #131475 - fmease:compiler-mv-obj-safe-dyn-compat-2, r=jieyouxu
Compiler & its UI tests: Rename remaining occurrences of "object safe" to "dyn compatible"

Follow-up to #130826.
Part of #130852.

1. 1st commit: Fix stupid oversights. Should've been part of #130826.
2. 2nd commit: Rename the unstable feature `object_safe_for_dispatch` to `dyn_compatible_for_dispatch`. Might not be worth the churn, you decide.
3. 3rd commit: Apply the renaming to all UI tests (contents and paths).
2024-10-10 22:00:50 +02:00
lcnr
d6fd45c2e3 impossible obligations check fast path 2024-10-10 06:09:50 -04:00
León Orell Valerian Liehr
2e7a52b22f
Rename feature object_safe_for_dispatch to dyn_compatible_for_dispatch 2024-10-10 00:57:59 +02:00
León Orell Valerian Liehr
62b24ea7c5
Compiler: Replace remaining occurrences of "object safe" with "dyn compatible" 2024-10-10 00:57:52 +02:00
Michael Goulet
7c552d56b2 Also fix first_method_vtable_slot 2024-09-30 13:17:33 -04:00
Michael Goulet
d87e0ca497 Extract trait_refs_are_compatible, make it instantiate binders 2024-09-30 13:17:33 -04:00
Michael Goulet
af3f212453 Instantiate binders in supertrait_vtable_slot 2024-09-30 13:17:33 -04:00
Matthias Krüger
4e510daed7
Rollup merge of #130866 - compiler-errors:dyn-instantiate-binder, r=lcnr
Allow instantiating object trait binder when upcasting

This PR fixes two bugs (that probably need an FCP).

### We use equality rather than subtyping for upcasting dyn conversions

This code should be valid:

```rust
#![feature(trait_upcasting)]

trait Foo: for<'h> Bar<'h> {}
trait Bar<'a> {}

fn foo(x: &dyn Foo) {
    let y: &dyn Bar<'static> = x;
}
```
But instead:

```
error[E0308]: mismatched types
 --> src/lib.rs:7:32
  |
7 |     let y: &dyn Bar<'static> = x;
  |                                ^ one type is more general than the other
  |
  = note: expected existential trait ref `for<'h> Bar<'h>`
             found existential trait ref `Bar<'_>`
```

And so should this:

```rust
#![feature(trait_upcasting)]

fn foo(x: &dyn for<'h> Fn(&'h ())) {
    let y: &dyn FnOnce(&'static ()) = x;
}
```

But instead:

```
error[E0308]: mismatched types
 --> src/lib.rs:4:39
  |
4 |     let y: &dyn FnOnce(&'static ()) = x;
  |                                       ^ one type is more general than the other
  |
  = note: expected existential trait ref `for<'h> FnOnce<(&'h (),)>`
             found existential trait ref `FnOnce<(&(),)>`
```

Specifically, both of these fail because we use *equality* when comparing the supertrait to the *target* of the unsize goal. For the first example, since our supertrait is `for<'h> Bar<'h>` but our target is `Bar<'static>`, there's a higher-ranked type mismatch even though we *should* be able to instantiate that supertrait binder when upcasting. Similarly for the second example.

### New solver uses equality rather than subtyping for no-op (i.e. non-upcasting) dyn conversions

This code should be valid in the new solver, like it is with the old solver:

```rust
// -Znext-solver

fn foo<'a>(x: &mut for<'h> dyn Fn(&'h ())) {
   let _: &mut dyn Fn(&'a ()) = x;
}
```

But instead:

```
error: lifetime may not live long enough
 --> <source>:2:11
  |
1 | fn foo<'a>(x: &mut dyn for<'h> Fn(&'h ())) {
  |        -- lifetime `'a` defined here
2 |    let _: &mut dyn Fn(&'a ()) = x;
  |           ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
  |
  = note: requirement occurs because of a mutable reference to `dyn Fn(&())`
```

Specifically, this fails because we try to coerce `&mut dyn for<'h> Fn(&'h ())` to `&mut dyn Fn(&'a ())`, which registers an `dyn for<'h> Fn(&'h ()): dyn Fn(&'a ())` goal. This fails because the new solver uses *equating* rather than *subtyping* in `Unsize` goals.

This is *mostly* not a problem... You may wonder why the same code passes on the new solver for immutable references:

```
// -Znext-solver

fn foo<'a>(x: &dyn Fn(&())) {
   let _: &dyn Fn(&'a ()) = x; // works
}
```

That's because in this case, we first try to coerce via `Unsize`, but due to the leak check the goal fails. Then, later in coercion, we fall back to a simple subtyping operation, which *does* work.

Since `&T` is covariant over `T`, but `&mut T` is invariant, that's where the discrepancy between these two examples crops up.

---

r? lcnr or reassign :D
2024-09-28 09:35:09 +02:00
Michael Goulet
d753aba3b3 Get rid of a_is_expected from ToTrace 2024-09-27 15:43:18 -04:00
Michael Goulet
4fb097a5de Instantiate binders when checking supertrait upcasting 2024-09-27 15:43:18 -04:00
Michael Goulet
d4ee408afc Check allow instantiating object trait binder when upcasting and in new solver 2024-09-26 22:26:29 -04:00
León Orell Valerian Liehr
01a063f9df
Compiler: Rename "object safe" to "dyn compatible" 2024-09-25 13:26:48 +02:00
Matthias Krüger
2bca5c4fc1
Rollup merge of #130714 - compiler-errors:try-structurally-resolve-const, r=BoxyUwU
Introduce `structurally_normalize_const`, use it in `rustc_hir_typeck`

Introduces `structurally_normalize_const` to typecking to separate the "eval a const" step from the "try to turn a valtree into a target usize" in HIR typeck, where we may still have infer vars and stuff around.

I also changed `check_expr_repeat` to move a double evaluation of a const into a single one. I'll leave inline comments.

r? ```@BoxyUwU```

I hesitated to really test this on the new solver where it probably matters for unevaluated consts. If you're worried about the side-effects, I'd be happy to craft some more tests 😄
2024-09-23 06:45:36 +02:00
Michael Goulet
c682aa162b Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
Michael Goulet
3b8089a320 Introduce structurally_normalize_const, use it in hir_typeck 2024-09-22 13:54:16 -04:00
Lukas Markeffsky
1999d065b7 skip normalizing param env if it is already normalized 2024-09-19 15:56:24 +02:00
Nicholas Nethercote
8d32578fe1 Rename and reorder lots of lifetimes.
- Replace non-standard names like 's, 'p, 'rg, 'ck, 'parent, 'this, and
  'me with vanilla 'a. These are cases where the original name isn't
  really any more informative than 'a.
- Replace names like 'cx, 'mir, and 'body with vanilla 'a when the lifetime
  applies to multiple fields and so the original lifetime name isn't
  really accurate.
- Put 'tcx last in lifetime lists, and 'a before 'b.
2024-09-13 15:46:20 +10:00
bors
394c4060d2 Auto merge of #130269 - Zalathar:rollup-coxzt2t, r=Zalathar
Rollup of 8 pull requests

Successful merges:

 - #125060 (Expand documentation of PathBuf, discussing lack of sanitization)
 - #129367 (Fix default/minimum deployment target for Aarch64 simulator targets)
 - #130156 (Add test for S_OBJNAME & update test for LF_BUILDINFO cl and cmd)
 - #130160 (Fix `slice::first_mut` docs)
 - #130235 (Simplify some nested `if` statements)
 - #130250 (Fix `clippy::useless_conversion`)
 - #130252 (Properly report error on `const gen fn`)
 - #130256 (Re-run coverage tests if `coverage-dump` was modified)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-09-12 12:56:55 +00:00
Stuart Cook
57020e0f8c
Rollup merge of #130250 - compiler-errors:useless-conversion, r=jieyouxu
Fix `clippy::useless_conversion`

Self-explanatory. Probably the last clippy change I'll actually put up since this is the only other one I've actually seen in the wild.
2024-09-12 20:37:17 +10:00
Michael Goulet
e866f8a97d Revert 'Stabilize -Znext-solver=coherence' 2024-09-11 17:57:04 -04:00
Michael Goulet
6d064295c8 clippy::useless_conversion 2024-09-11 17:52:53 -04:00
Michael Goulet
af8d911d63 Also fix if in else 2024-09-11 17:24:01 -04:00
Michael Goulet
954419aab0 Simplify some nested if statements 2024-09-11 13:45:23 -04:00
bors
26b5599e4d Auto merge of #128776 - Bryanskiy:deep-reject-ctxt, r=lcnr
Use `DeepRejectCtxt` to quickly reject `ParamEnv` candidates

The description is on the [zulip thread](https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types/topic/.5Basking.20for.20help.5D.20.60DeepRejectCtxt.60.20for.20param.20env.20candidates)

r? `@lcnr`
2024-09-06 19:50:48 +00:00
lcnr
1a893ac648 stabilize -Znext-solver=coherence 2024-09-05 07:57:16 +00:00
lcnr
6188aae369 do not attempt to prove unknowable goals 2024-09-03 08:35:23 +02:00
bors
6199b69c53 Auto merge of #129777 - nnethercote:unreachable_pub-4, r=Urgau
Add `unreachable_pub`, round 4

A follow-up to #129732.

r? `@Urgau`
2024-09-03 01:27:20 +00:00
Nicholas Nethercote
2e358e633d Add warn(unreachable_pub) to rustc_trait_selection. 2024-09-03 08:49:54 +10:00
Matthias Krüger
929b308579
Rollup merge of #129878 - Sajjon:sajjon_fix_typos_batch_3, r=jieyouxu
chore: Fix typos in 'compiler' (batch 3)

Batch 3/3: Fixes typos in `compiler`

(See [issue](https://github.com/rust-lang/rust/issues/129874) tracking all PRs with typos fixes)
2024-09-02 22:35:21 +02:00
Bryanskiy
c51953f4d8 Use DeepRejectCtxt to quickly reject ParamEnv candidates 2024-09-02 19:59:18 +03:00
Alexander Cyon
5780c1ca5e
chore: Fix typos in 'compiler' (batch 3) 2024-09-02 07:33:41 +02:00
Jakub Beránek
47e6b5deed Revert "Auto merge of #127537 - veluca93:struct_tf, r=BoxyUwU"
This reverts commit acb4e8b625, reversing
changes made to 100fde5246.
2024-09-01 16:35:53 +02:00
Matthias Krüger
7d025bb63d
Rollup merge of #129767 - nnethercote:rm-extern-crate-tracing-4, r=jieyouxu
Remove `#[macro_use] extern crate tracing`, round 4

Because explicit importing of macros via use items is nicer (more standard and readable) than implicit importing via #[macro_use]. Continuing the work from #124511, #124914, and #125434. After this PR no `rustc_*` crates use `#[macro_use] extern crate tracing` except for `rustc_codegen_gcc` which is a special case and I will do separately.

r? ```@jieyouxu```
2024-08-31 14:46:11 +02:00
Matthias Krüger
5f10a99c7a
Rollup merge of #129725 - compiler-errors:predicates-of, r=fmease
Stop using `ty::GenericPredicates` for non-predicates_of queries

`GenericPredicates` is a struct of several parts: A list of of an item's own predicates, and a parent def id (and some effects related stuff, but ignore that since it's kinda irrelevant). When instantiating these generic predicates, it calls `predicates_of` on the parent and instantiates its predicates, and appends the item's own instantiated predicates too:

acb4e8b625/compiler/rustc_middle/src/ty/generics.rs (L407-L413)

Notice how this should result in a recursive set of calls to `predicates_of`... However, `GenericPredicates` is *also* misused by a bunch of *other* queries as a convenient way of passing around a list of predicates. For these queries, we don't ever set the parent def id of the `GenericPredicates`, but if we did, then this would be very easy to mistakenly call `predicates_of` instead of some other intended parent query.

Given that footgun, and the fact that we don't ever even *use* the parent def id in the `GenericPredicates` returned from queries like `explicit_super_predicates_of`, It really has no benefit over just returning `&'tcx [(Clause<'tcx>, Span)]`.

This PR additionally opts to wrap the results of `EarlyBinder`, as we've tended to use that in the return type of these kinds of queries to properly convey that the user has params to deal with, and it also gives a convenient way of iterating over a slice of things after instantiating.
2024-08-31 10:08:57 +02:00
Nicholas Nethercote
4b3fa8e9f0 Remove #[macro_use] extern crate tracing from rustc_trait_selection. 2024-08-30 17:14:59 +10:00
Michael Goulet
92004523db Stop using ty::GenericPredicates for non-predicates_of queries 2024-08-29 00:17:40 -04:00
Luca Versari
7eb4cfeace Implement RFC 3525. 2024-08-28 09:54:23 +02:00
Michael Goulet
0b2525c787 Simplify some redundant field names 2024-08-21 01:31:42 -04:00
Matthias Krüger
5cb30b7e9d
Rollup merge of #129217 - jswrenn:transmute-lifetimes, r=compiler-errors
safe transmute: check lifetimes

Modifies `BikeshedIntrinsicFrom` to forbid lifetime extensions on references. This static check can be opted out of with the `Assume::lifetimes` flag.

Fixes #129097

Tracking Issue: https://github.com/rust-lang/rust/issues/99571

 r​? `@compiler-errors`
2024-08-19 20:14:56 +02:00
Jack Wrenn
17995d5cc2 safe transmute: forbid reference lifetime extension
Modifies `BikeshedIntrinsicFrom` to forbid lifetime extensions on
references. This static check can be opted out of with the
`Assume::lifetimes` flag.

Fixes #129097
2024-08-18 18:31:06 +00:00
Luca Versari
7fd62320fe Fix order of normalization and recursion in const folding.
Fixes #126831.

Without this patch, type normalization is not always idempotent, which
leads to all sorts of bugs in places that assume that normalizing a
normalized type does nothing.
2024-08-18 00:07:41 +02:00
Jubilee
4f46643698
Rollup merge of #129078 - lcnr:scrape_region_constraints-use-ocx, r=compiler-errors
`ParamEnvAnd::fully_perform`: we have an `ocx`, use it

cc #123669

r? ``@compiler-errors``
2024-08-15 18:44:18 -07:00
Matthias Krüger
f3df807207
Rollup merge of #129106 - compiler-errors:unused-type-ops, r=jieyouxu
Remove redundant type ops: `Eq`/`Subtype`

r? lcnr or anyone really
2024-08-15 19:32:37 +02:00
Michael Goulet
f264e5d011 Remove redundant type ops 2024-08-14 14:18:17 -04:00
lcnr
3a02047d52 if we have an ocx, use it 2024-08-14 09:36:53 +02:00
bors
9859bf27fd Auto merge of #129076 - matthiaskrgr:rollup-rg8mi2x, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #128410 (Migrate `remap-path-prefix-dwarf` `run-make` test to rmake)
 - #128759 (alloc: add ToString specialization for `&&str`)
 - #128873 (Add windows-targets crate to std's sysroot)
 - #129001 (chore(lib): Enhance documentation for core::fmt::Formatter's write_fm…)
 - #129061 (Use `is_lang_item` more)
 - #129062 (Remove a no-longer-true assert)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-08-14 04:17:13 +00:00
Matthias Krüger
cd6852b9ea
Rollup merge of #129061 - compiler-errors:lang-item, r=Urgau
Use `is_lang_item` more

Few places that I missed since introducing `TyCtxt::is_lang_item`.
2024-08-14 05:05:52 +02:00
bors
e9c965df7b Auto merge of #128812 - nnethercote:shrink-TyKind-FnPtr, r=compiler-errors
Shrink `TyKind::FnPtr`.

By splitting the `FnSig` within `TyKind::FnPtr` into `FnSigTys` and `FnHeader`, which can be packed more efficiently. This reduces the size of the hot `TyKind` type from 32 bytes to 24 bytes on 64-bit platforms. This reduces peak memory usage by a few percent on some benchmarks. It also reduces cache misses and page faults similarly, though this doesn't translate to clear cycles or wall-time improvements on CI.

r? `@compiler-errors`
2024-08-14 00:56:53 +00:00
Michael Goulet
bac19686a5 Use is_lang_item more 2024-08-13 16:44:53 -04:00
Matthias Krüger
4c49418472
Rollup merge of #128712 - compiler-errors:normalize-borrowck, r=lcnr
Normalize struct tail properly for `dyn` ptr-to-ptr casting in new solver

Realized that the new solver didn't handle ptr-to-ptr casting correctly.

r? lcnr

Built on #128694
2024-08-12 23:10:50 +02:00
Guillaume Gomez
7c6dca9050
Rollup merge of #128978 - compiler-errors:assert-matches, r=jieyouxu
Use `assert_matches` around the compiler more

It's a useful assertion, especially since it actually prints out the LHS.
2024-08-12 17:09:19 +02:00
Michael Goulet
f15997ffec Remove struct_tail_no_normalization 2024-08-11 19:40:03 -04:00
Michael Goulet
b5d2079fb9 Rename normalization functions to raw 2024-08-11 19:40:03 -04:00
Michael Goulet
c361c924a0 Use assert_matches around the compiler 2024-08-11 12:25:39 -04:00
bors
48090b11b5 Auto merge of #128746 - compiler-errors:cache-super-outlives, r=lcnr
Cache supertrait outlives of impl header for soundness check

This caches the results of computing the transitive supertraits of an impl and filtering it to its outlives obligations. This is purely an optimization to improve https://github.com/rust-lang/rust/pull/124336.
2024-08-10 10:22:06 +00:00
Nicholas Nethercote
c4717cc9d1 Shrink TyKind::FnPtr.
By splitting the `FnSig` within `TyKind::FnPtr` into `FnSigTys` and
`FnHeader`, which can be packed more efficiently. This reduces the size
of the hot `TyKind` type from 32 bytes to 24 bytes on 64-bit platforms.
This reduces peak memory usage by a few percent on some benchmarks. It
also reduces cache misses and page faults similarly, though this doesn't
translate to clear cycles or wall-time improvements on CI.
2024-08-09 14:33:25 +10:00
Michael Goulet
ec1c424293 Don't implement AsyncFn for FnDef/FnPtr that wouldnt implement Fn 2024-08-08 14:07:31 -04:00
Michael Goulet
79228526bf Cache supertrait outlives of impl header for soundness check 2024-08-06 13:33:32 -04:00
bors
f7eefec4e0 Auto merge of #128689 - matthiaskrgr:rollup-ukyn8wq, r=matthiaskrgr
Rollup of 5 pull requests

Successful merges:

 - #128385 (rustdoc-json: discard non-local inherent impls for primitives)
 - #128559 (Don't re-elaborated already elaborated caller bounds in method probe)
 - #128631 (handle crates when they are not specified for std docs)
 - #128664 (Add `Debug` impls to API types in `rustc_codegen_ssa`)
 - #128686 (fix the invalid argument type)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-08-05 17:03:58 +00:00
Michael Goulet
34e087890c Don't re-elaborated already elaborated caller bounds in method probe 2024-08-05 10:48:20 -04:00
Michael Goulet
fa9ae7b9d3 Elaborate supertraits in dyn candidates 2024-08-05 10:03:17 -04:00
Michael Goulet
6a891ec4fe Enforce supertrait outlives obligations hold when confirming impl 2024-08-05 09:55:14 -04:00
Bryanskiy
34fcf92ea0 Add special-case for [T, 0] in dropck 2024-07-31 16:15:05 +03:00
Nicholas Nethercote
84ac80f192 Reformat use declarations.
The previous commit updated `rustfmt.toml` appropriately. This commit is
the outcome of running `x fmt --all` with the new formatting options.
2024-07-29 08:26:52 +10:00
Michael Goulet
d5656059a1 Make coroutine-closures possible to be cloned 2024-07-26 12:53:53 -04:00
Matthias Krüger
a88354831b
Rollup merge of #126090 - compiler-errors:supertrait-assoc-ty-unsoundness, r=lcnr
Fix supertrait associated type unsoundness

### What?

Object safety allows us to name `Self::Assoc` associated types in certain positions if they come from our trait or one of our supertraits. When this check was implemented, I think it failed to consider that supertraits can have different args, and it was only checking def-id equality.

This is problematic, since we can sneak different implementations in by implementing `Supertrait<NotActuallyTheSupertraitSubsts>` for a `dyn` type. This can be used to implement an unsound transmute function. See the committed test.

### How do we fix it?

We consider the whole trait ref when checking for supertraits. Right now, this is implemented using equality *without* normalization. We erase regions since those don't affect trait selection.

This is a limitation that could theoretically affect code that should be accepted, but doesn't matter in practice -- there are 0 crater regression. We could make this check stronger, but I would be worried about cycle issues. I assume that most people are writing `Self::Assoc` so they don't really care about the trait ref being normalized.

---

### What is up w the stacked commit

This is built on top of https://github.com/rust-lang/rust/pull/122804 though that's really not related, it's just easier to make this modification with the changes to the object safety code that I did in that PR. The only thing is that PR may make this unsoundness slightly easier to abuse, since there are more positions that allow self-associated-types -- I am happy to stall that change until this PR merges.

---

Fixes #126079

r? lcnr
2024-07-26 00:57:20 +02:00
Matthias Krüger
1fda084290
Rollup merge of #128160 - compiler-errors:auto, r=jackh726
Don't ICE when auto trait has assoc ty in old solver

Kinda a pointless change to make, but it's observable w/o the feature gate, so let's just fix it. I reintroduced this ICE when I removed the "auto impl" kind from `ImplSource` in #112687.

Fixes #117829
Fixes #127746
2024-07-25 04:43:20 +02:00
Michael Goulet
0919d0714e Don't ICE when auto trait has assoc ty in old solver 2024-07-24 17:19:44 -04:00
Oli Scherer
8ea461da55 Do not assemble candidates for auto traits of opaque types in their defining scope 2024-07-24 16:00:48 +00:00
Oli Scherer
acba6449f8 Do not try to reveal hidden types when trying to prove Freeze in the defining scope 2024-07-24 16:00:48 +00:00
Oli Scherer
61b5e11c47 Don't use global caches if opaques can be defined 2024-07-24 10:45:21 +00:00
Michael Goulet
ce8a625092 Move all error reporting into rustc_trait_selection 2024-07-21 22:34:35 -04:00
bors
9629b90b3f Auto merge of #127722 - BoxyUwU:new_adt_const_params_limitations, r=compiler-errors
Forbid borrows and unsized types from being used as the type of a const generic under `adt_const_params`

Fixes #112219
Fixes #112124
Fixes #112125

### Motivation

Currently the `adt_const_params` feature allows writing `Foo<const N: [u8]>` this is entirely useless as it is not possible to write an expression which evaluates to a type that is not `Sized`. In order to actually use unsized types in const generics they are typically written as `const N: &[u8]` which *is* possible to provide a value of.

Unfortunately allowing the types of const parameters to contain references is non trivial (#120961) as it introduces a number of difficult questions about how equality of references in the type system should behave. References in the types of const generics is largely only useful for using unsized types in const generics.

This PR introduces a new feature gate `unsized_const_parameters` and moves support for `const N: [u8]` and `const N: &...` from `adt_const_params` into it. The goal here hopefully is to experiment with allowing `const N: [u8]` to work without references and then eventually completely forbid references in const generics.

Splitting this out into a new feature gate means that stabilization of `adt_const_params` does not have to resolve #120961 which is the only remaining "big" blocker for the feature. Remaining issues after this are a few ICEs and naming bikeshed for `ConstParamTy`.

### Implementation

The implementation is slightly subtle here as we would like to ensure that a stabilization of `adt_const_params` is forwards compatible with any outcome of `unsized_const_parameters`. This is inherently tricky as we do not support unstable trait implementations and we determine whether a type is valid as the type of a const parameter via a trait bound.

There are a few constraints here:
- We would like to *allow for the possibility* of adding a `Sized` supertrait to `ConstParamTy` in the event that we wind up opting to not support unsized types and instead requiring people to write the 'sized version', e.g. `const N: [u8; M]` instead of `const N: [u8]`.
- Crates should be able to enable `unsized_const_parameters` and write trait implementations of `ConstParamTy` for `!Sized` types without downstream crates that only enable `adt_const_params` being able to observe this (required for std to be able to `impl<T> ConstParamTy for [T]`

Ultimately the way this is accomplished is via having two traits (sad), `ConstParamTy` and `UnsizedConstParamTy`. Depending on whether `unsized_const_parameters` is enabled or not we change which trait is used to check whether a type is allowed to be a const parameter.

Long term (when stabilizing `UnsizedConstParamTy`) it should be possible to completely merge these traits (and derive macros), only having a single `trait ConstParamTy` and `macro ConstParamTy`.

Under `adt_const_params` it is now illegal to directly refer to `ConstParamTy` it is only used as an internal impl detail by `derive(ConstParamTy)` and checking const parameters are well formed. This is necessary in order to ensure forwards compatibility with all possible future directions for `feature(unsized_const_parameters)`.

Generally the intuition here should be that `ConstParamTy` is the stable trait that everything uses, and `UnsizedConstParamTy` is that plus unstable implementations (well, I suppose `ConstParamTy` isn't stable yet :P).
2024-07-21 05:36:21 +00:00
Matthias Krüger
9f8c618a90
Rollup merge of #127856 - RalfJung:interpret-cast-sanity, r=oli-obk
interpret: add sanity check in dyn upcast to double-check what codegen does

For dyn receiver calls, we already have two codepaths: look up the function to call by indexing into the vtable, or alternatively resolve the DefId given the dynamic type of the receiver. With debug assertions enabled, the interpreter does both and compares the results. (Without debug assertions we always use the vtable as it is simpler.)

This PR does the same for dyn trait upcasts. However, for casts *not* using the vtable is the easier thing to do, so now the vtable path is the debug-assertion-only path. In particular, there are cases where the vtable does not contain a pointer for upcasts but instead reuses the old pointer: when the supertrait vtable is a prefix of the larger vtable. We don't want to expose this optimization and detect UB if people do a transmute assuming this optimization, so we cannot in general use the vtable indexing path.

r? ``@oli-obk``
2024-07-19 17:06:50 +02:00
bors
8c3a94a1c7 Auto merge of #125915 - camelid:const-arg-refactor, r=BoxyUwU
Represent type-level consts with new-and-improved `hir::ConstArg`

### Summary

This is a step toward `min_generic_const_exprs`. We now represent all const
generic arguments using an enum that differentiates between const *paths*
(temporarily just bare const params) and arbitrary anon consts that may perform
computations. This will enable us to cleanly implement the `min_generic_const_args`
plan of allowing the use of generics in paths used as const args, while
disallowing their use in arbitrary anon consts. Here is a summary of the salient
aspects of this change:

- Add `current_def_id_parent` to `LoweringContext`

  This is needed to track anon const parents properly once we implement
  `ConstArgKind::Path` (which requires moving anon const def-creation
  outside of `DefCollector`).

- Create `hir::ConstArgKind` enum with `Path` and `Anon` variants. Use it in the
  existing `hir::ConstArg` struct, replacing the previous `hir::AnonConst` field.

- Use `ConstArg` for all instances of const args. Specifically, use it instead
  of `AnonConst` for assoc item constraints, array lengths, and const param
  defaults.

- Some `ast::AnonConst`s now have their `DefId`s created in
  rustc_ast_lowering rather than `DefCollector`. This is because in some
  cases they will end up becoming a `ConstArgKind::Path` instead, which
  has no `DefId`. We have to solve this in a hacky way where we guess
  whether the `AnonConst` could end up as a path const since we can't
  know for sure until after name resolution (`N` could refer to a free
  const or a nullary struct). If it has no chance as being a const
  param, then we create a `DefId` in `DefCollector` -- otherwise we
  decide during ast_lowering. This will have to be updated once all path
  consts use `ConstArgKind::Path`.

- We explicitly use `ConstArgHasType` for array lengths, rather than
  implicitly relying on anon const type feeding -- this is due to the
  addition of `ConstArgKind::Path`.

- Some tests have their outputs changed, but the changes are for the
  most part minor (including removing duplicate or almost-duplicate
  errors). One test now ICEs, but it is for an incomplete, unstable
  feature and is now tracked at https://github.com/rust-lang/rust/issues/127009.

### Followup items post-merge

- Use `ConstArgKind::Path` for all const paths, not just const params.
- Fix (no github dont close this issue) #127009
- If a path in generic args doesn't resolve as a type, try to resolve as a const
  instead (do this in rustc_resolve). Then remove the special-casing from
  `rustc_ast_lowering`, so that all params will automatically be lowered as
  `ConstArgKind::Path`.
- (?) Consider making `const_evaluatable_unchecked` a hard error, or at least
  trying it in crater

r? `@BoxyUwU`
2024-07-19 08:44:51 +00:00
Michael Goulet
8dbb63a585 Remove tag field from relations 2024-07-18 14:34:05 -04:00
Ralf Jung
e613bc92a1 const_to_pat: cleanup leftovers from when we had to deal with non-structural constants 2024-07-18 11:58:16 +02:00
Ralf Jung
fa74a9e6aa valtree construction: keep track of which type was valtree-incompatible 2024-07-18 11:58:16 +02:00
Ralf Jung
a7b80819e9 interpret: add sanity check in dyn upcast to double-check what codegen does 2024-07-18 11:41:10 +02:00
Michael Goulet
0b5ce54bc2 Fix relations 2024-07-17 10:46:10 -04:00
Boxy
d0c11bf6e3 Split part of adt_const_params into unsized_const_params 2024-07-17 11:01:29 +01:00
Boxy
42cc42b942 Forbid !Sized types and references 2024-07-17 11:01:29 +01:00
Noah Lev
37ed7a4438 Add ConstArgKind::Path and make ConstArg its own HIR node
This is a very large commit since a lot needs to be changed in order to
make the tests pass. The salient changes are:

- `ConstArgKind` gets a new `Path` variant, and all const params are now
  represented using it. Non-param paths still use `ConstArgKind::Anon`
  to prevent this change from getting too large, but they will soon use
  the `Path` variant too.

- `ConstArg` gets a distinct `hir_id` field and its own variant in
  `hir::Node`. This affected many parts of the compiler that expected
  the parent of an `AnonConst` to be the containing context (e.g., an
  array repeat expression). They have been changed to check the
  "grandparent" where necessary.

- Some `ast::AnonConst`s now have their `DefId`s created in
  rustc_ast_lowering rather than `DefCollector`. This is because in some
  cases they will end up becoming a `ConstArgKind::Path` instead, which
  has no `DefId`. We have to solve this in a hacky way where we guess
  whether the `AnonConst` could end up as a path const since we can't
  know for sure until after name resolution (`N` could refer to a free
  const or a nullary struct). If it has no chance as being a const
  param, then we create a `DefId` in `DefCollector` -- otherwise we
  decide during ast_lowering. This will have to be updated once all path
  consts use `ConstArgKind::Path`.

- We explicitly use `ConstArgHasType` for array lengths, rather than
  implicitly relying on anon const type feeding -- this is due to the
  addition of `ConstArgKind::Path`.

- Some tests have their outputs changed, but the changes are for the
  most part minor (including removing duplicate or almost-duplicate
  errors). One test now ICEs, but it is for an incomplete, unstable
  feature and is now tracked at #127009.
2024-07-16 19:27:28 -07:00
Michael Goulet
172cf9bef3 Fix unsoundness when associated types dont actually come from supertraits 2024-07-15 14:17:32 -04:00
Michael Goulet
8edf9b8084 Item bounds can reference self projections and still be object safe 2024-07-15 14:16:48 -04:00
Michael Goulet
2c8bbeebf1 Remove fully_normalize 2024-07-11 19:15:04 -04:00
Matthias Krüger
22df186d6f
Rollup merge of #127570 - lcnr:normalize-cool, r=compiler-errors
small normalization improvement

r? `@compiler-errors`
2024-07-10 17:54:29 +02:00
lcnr
e00fd781c9 simplify and future-proof needs_normalization 2024-07-10 15:56:20 +02:00
lcnr
f77394fdf3 instantiate higher ranked goals in candidate selection
reverts #119820
2024-07-10 14:13:16 +02:00
Michael Goulet
7af825fea4 Split out overflow handling into its own module 2024-07-09 09:51:56 -04:00
Michael Goulet
fe4c995ccb Move trait selection error reporting to its own top-level module 2024-07-08 16:04:47 -04:00
许杰友 Jieyou Xu (Joe)
ffb93361b4
Rollup merge of #127439 - compiler-errors:uplift-elaborate, r=lcnr
Uplift elaboration into `rustc_type_ir`

Allows us to deduplicate and consolidate elaboration (including these stupid elaboration duplicate fns i added for pretty printing like 3 years ago) so I'm pretty hyped about this change :3

r? lcnr
2024-07-08 13:04:33 +08:00
许杰友 Jieyou Xu (Joe)
928d71f17b
Rollup merge of #127437 - compiler-errors:uplift-trait-ref-is-knowable, r=lcnr
Uplift trait ref is knowable into `rustc_next_trait_solver`

Self-explanatory. Eliminates one more delegate method.

r? lcnr cc ``@fmease``
2024-07-08 13:04:32 +08:00
bors
89aefb9c53 Auto merge of #127172 - compiler-errors:full-can_eq-everywhere, r=lcnr
Make `can_eq` process obligations (almost) everywhere

Move `can_eq` to an extension trait on `InferCtxt` in `rustc_trait_selection`, and change it so that it processes obligations. This should strengthen it to be more accurate in some cases, but is most important for the new trait solver which delays relating aliases to `AliasRelate` goals. Without this, we always basically just return true when passing aliases to `can_eq`, which can lead to weird errors, for example #127149.

I'm not actually certain if we should *have* `can_eq` be called on the good path. In cases where we need `can_eq`, we probably should just be using a regular probe.

Fixes #127149

r? lcnr
2024-07-07 23:03:48 +00:00
Michael Goulet
a982471e07 Uplift trait_ref_is_knowable and friends 2024-07-07 11:10:32 -04:00
Michael Goulet
b2e30bdec4 Add fundamental to trait def 2024-07-07 11:10:32 -04:00
Michael Goulet
58aad3c72c iter_identity is a better name 2024-07-07 00:12:35 -04:00
bors
9e27377bec Auto merge of #127404 - compiler-errors:rpitit-entailment-false-positive, r=oli-obk
Don't try to label `ObligationCauseCode::CompareImplItem` for an RPITIT, since it has no name

The old (current) trait solver has a limitation that when a where clause in param-env must be normalized using the same where clause, then we get spurious errors in `normalize_param_env_or_error`. I don't think there's an issue tracking it, but it's the root cause for many of the "fixed-by-next-solver" labeled issues.

Specifically, these errors may occur when checking predicate entailment of the GAT that comes out of desugaring RPITITs. Since we use `ObligationCauseCode::CompareImplItem` for these predicates, we try calling `item_name` on an RPITIT which fails, since the RPITIT has no name.

We simply suppress this logic when we're reporting a predicate entailment error for an RPITIT. RPITITs should never have predicate entailment errors, *by construction*, but they may due to this bug in the old solver.

Addresses the ICE in #127331, though doesn't fix the underlying issue (which is fundamental to the old solver).

r? types
2024-07-07 03:22:12 +00:00
Michael Goulet
d6276b37ea Don't try to label ObligationCauseCode::CompareImplItem for an RPITIT, since it has no name 2024-07-06 15:20:37 -04:00
Michael Goulet
cc6c5de39d Import via rustc_type_ir::outlives
We could use rustc_middle::ty::outlives I guess?
2024-07-06 10:47:46 -04:00
Michael Goulet
23c6f23b21 Uplift push_outlives_components 2024-07-06 10:47:46 -04:00
Michael Goulet
fb8d5f1e13 Actually just make can_eq process obligations (almost) everywhere 2024-07-05 11:59:54 -04:00
Oli Scherer
7dca61b68b Use ControlFlow results for visitors that are only looking for a single value 2024-07-05 15:00:40 +00:00
bors
c872a1418a Auto merge of #125507 - compiler-errors:type-length-limit, r=lcnr
Re-implement a type-size based limit

r? lcnr

This PR reintroduces the type length limit added in #37789, which was accidentally made practically useless by the caching changes to `Ty::walk` in #72412, which caused the `walk` function to no longer walk over identical elements.

Hitting this length limit is not fatal unless we are in codegen -- so it shouldn't affect passes like the mir inliner which creates potentially very large types (which we observed, for example, when the new trait solver compiles `itertools` in `--release` mode).

This also increases the type length limit from `1048576 == 2 ** 20` to `2 ** 24`, which covers all of the code that can be reached with craterbot-check. Individual crates can increase the length limit further if desired.

Perf regression is mild and I think we should accept it -- reinstating this limit is important for the new trait solver and to make sure we don't accidentally hit more type-size related regressions in the future.

Fixes #125460
2024-07-03 11:56:36 +00:00
Jacob Pratt
b1b9804f5a
Rollup merge of #126403 - compiler-errors:better-type-errors, r=lcnr
Actually report normalization-based type errors correctly for alias-relate obligations in new solver

We have some special casing to report type mismatch errors that come from projection predicates, but we don't do that for alias-relate obligations. This PR implements that. There's a bit of code duplication, but 🤷

Best reviewed without whitespace.

r? lcnr
2024-07-03 03:03:14 -04:00
bors
d163e5e515 Auto merge of #123737 - compiler-errors:alias-wf, r=lcnr
Check alias args for WF even if they have escaping bound vars

#### What

This PR stops skipping arguments of aliases if they have escaping bound vars, instead recursing into them and only discarding the resulting obligations referencing bounds vars.

#### An example:

From the test:
```
trait Trait {
    type Gat<U: ?Sized>;
}

fn test<T>(f: for<'a> fn(<&'a T as Trait>::Gat<&'a [str]>)) where for<'a> &'a T: Trait {}
//~^ ERROR the size for values of type `[()]` cannot be known at compilation time

fn main() {}
```

We now prove that `str: Sized` in order for `&'a [str]` to be well-formed. We were previously unconditionally skipping over `&'a [str]` as it referenced a buond variable. We now recurse into it and instead only discard the `[str]: 'a` obligation because of the escaping bound vars.

#### Why?

This is a change that improves consistency about proving well-formedness earlier in the pipeline, which is necessary for future work on where-bounds in binders and correctly handling higher-ranked implied bounds. I don't expect this to fix any unsoundness.

#### What doesn't it fix?

Specifically, this doesn't check projection predicates' components are well-formed, because there are too many regressions: https://github.com/rust-lang/rust/pull/123737#issuecomment-2052198478
2024-07-03 03:48:06 +00:00
Michael Goulet
ecdaff240d Actually report normalization-based type errors correctly for alias-relate obligations in new solver 2024-07-02 16:39:57 -04:00
Michael Goulet
3273ccea4b Fix spans 2024-07-02 15:48:48 -04:00
Michael Goulet
d3a742bde9 Miscellaneous renaming 2024-07-02 15:48:48 -04:00
Matthias Krüger
a10c231118
Rollup merge of #127230 - hattizai:patch01, r=saethlin
chore: remove duplicate words

remove duplicate words in comments to improve readability.
2024-07-02 17:47:50 +02:00
Matthias Krüger
36da46ab98
Rollup merge of #127146 - compiler-errors:fast-reject, r=lcnr
Uplift fast rejection to new solver

Self explanatory.

r? lcnr
2024-07-02 17:47:47 +02:00
hattizai
ada9fda7c3 chore: remove duplicate words 2024-07-02 11:25:31 +08:00
bors
7b21c18fe4 Auto merge of #126996 - oli-obk:do_not_count_errors, r=nnethercote
Automatically taint InferCtxt when errors are emitted

r? `@nnethercote`

Basically `InferCtxt::dcx` now returns a `DiagCtxt` that refers back to the `Cell<Option<ErrorGuaranteed>>` of the `InferCtxt` and thus when invoking `Diag::emit`, and the diagnostic is an error, we taint the `InferCtxt` directly.

That change on its own has no effect at all, because `InferCtxt` already tracks whether errors have been emitted by recording the global error count when it gets opened, and checking at the end whether the count changed. So I removed that error count check, which had a bit of fallout that I immediately fixed by invoking `InferCtxt::dcx` instead of `TyCtxt::dcx` in a bunch of places.

The remaining new errors are because an error was reported in another query, and never bubbled up. I think they are minor enough for this to be ok, and sometimes it actually improves diagnostics, by not silencing useful diagnostics anymore.

fixes #126485 (cc `@olafes)`

There are more improvements we can do (like tainting in hir ty lowering), but I would rather do that in follow up PRs, because it requires some refactorings.
2024-07-01 06:35:58 +00:00
Michael Goulet
53db64168f Uplift fast rejection to new solver 2024-06-30 00:27:35 -04:00
bors
ba1d7f4a08 Auto merge of #120639 - fee1-dead-contrib:new-effects-desugaring, r=oli-obk
Implement new effects desugaring

cc `@rust-lang/project-const-traits.` Will write down notes once I have finished.

* [x] See if we want `T: Tr` to desugar into `T: Tr, T::Effects: Compat<true>`
* [x] Fix ICEs on `type Assoc: ~const Tr` and `type Assoc<T: ~const Tr>`
* [ ] add types and traits to minicore test
* [ ] update rustc-dev-guide

Fixes #119717
Fixes #123664
Fixes #124857
Fixes #126148
2024-06-29 20:08:10 +00:00
Deadbeef
72e8244e64 implement new effects desugaring 2024-06-28 10:57:35 +00:00
Michael Goulet
81c2c57519 Make queries more explicit 2024-06-27 12:03:57 -04:00
Oli Scherer
86c8eae774 Automatically taint InferCtxt when errors are emitted 2024-06-26 16:01:45 +00:00
Oli Scherer
5988078aa2 Restrict diagnostic context lifetime of InferCtxt to itself instead of TyCtxt 2024-06-26 16:01:44 +00:00
Oli Scherer
79ac8982ca Restrict diagnostic context lifetime of TypeErrCtxt to InferCtxt instead of TyCtxt 2024-06-26 16:01:44 +00:00
bors
164e1297e1 Auto merge of #125610 - oli-obk:define_opaque_types14, r=compiler-errors
Allow constraining opaque types during various unsizing casts

allows unsizing of tuples, arrays and Adts to constraint opaque types in their generic parameters to concrete types on either side of the unsizing cast.

Also allows constraining opaque types during trait object casts that only differ in auto traits or lifetimes.

cc #116652
2024-06-25 05:09:30 +00:00
bors
5b270e1198 Auto merge of #126813 - compiler-errors:SliceLike, r=lcnr
Add `SliceLike` to `rustc_type_ir`, use it in the generic solver code (+ some other changes)

First, we split out `TraitRef::new_from_args` which takes *just* `ty::GenericArgsRef` from `TraitRef::new` which takes `impl IntoIterator<Item: Into<GenericArg>>`. I will explain in a minute why.

Second, we introduce `SliceLike`, which allows us to be generic over `List<T>` and `[T]`. This trait has an `as_slice()` and `into_iter()` method, and some other convenience functions. However, importantly, since types like `I::GenericArgs` now implement `SliceLike` rather than `IntoIter<Item = I::GenericArg>`, we can't use `TraitRef::new` on this directly. That's where `new_from_args` comes in.

Finally, we adjust all the code to use these slice operators. Some things get simpler, some things get a bit more annoying since we need to use `as_slice()` in a few places. 🤷

r? lcnr
2024-06-25 00:33:49 +00:00
Michael Goulet
f26cc349d9 Split out IntoIterator and non-Iterator constructors for AliasTy/AliasTerm/TraitRef/projection 2024-06-24 11:28:21 -04:00
Pavel Grigorenko
ba5ec1fc5c Suggest inline const blocks for array initialization 2024-06-24 15:30:24 +03:00
Michael Goulet
db638ab968 Rename a bunch of things 2024-06-21 12:32:05 -04:00
Matthias Krüger
ef2e8bfcbf
Rollup merge of #126717 - nnethercote:rustfmt-use-pre-cleanups, r=jieyouxu
Clean up some comments near `use` declarations

#125443 will reformat all `use` declarations in the repository. There are a few edge cases involving comments on `use` declarations that require care. This PR cleans up some clumsy comment cases, taking us a step closer to #125443 being able to merge.

r? ``@lqd``
2024-06-20 14:07:04 +02:00
Matthias Krüger
e7be3562b7
Rollup merge of #126620 - oli-obk:taint_errors, r=fee1-dead
Actually taint InferCtxt when a fulfillment error is emitted

And avoid checking the global error counter

fixes #122044
fixes #123255
fixes #123276
fixes #125799
2024-06-20 07:52:43 +02:00
Nicholas Nethercote
665821cb60 Add blank lines after module-level //! comments.
Most modules have such a blank line, but some don't. Inserting the blank
line makes it clearer that the `//!` comments are describing the entire
module, rather than the `use` declaration(s) that immediately follows.
2024-06-20 09:23:20 +10:00
Oli Scherer
e4c9a8cf9b Const generic parameters aren't bounds, even if we end up erroring because of the bound that binds the parameter's type 2024-06-19 14:58:29 +00:00
Oli Scherer
4a86ef6f4c Allow constraining opaque types during auto trait casting 2024-06-19 08:28:31 +00:00
Oli Scherer
4dcb70b8cf Allow constraining opaque types during unsizing 2024-06-19 08:28:31 +00:00
Oli Scherer
3594a19f2a Taint infcx when reporting errors 2024-06-19 04:41:56 +00:00
bors
8fcd4dd08e Auto merge of #126614 - compiler-errors:uplift-next-trait-solver, r=lcnr
Uplift next trait solver to `rustc_next_trait_solver`

🎉

There's so many FIXMEs! Sorry! Ideally this merges with the FIXMEs and we track and squash them over the near future.

Also, this still doesn't build on anything other than rustc. I still need to fix `feature = "nightly"` in `rustc_type_ir`, and remove and fix all the nightly feature usage in the new trait solver (notably: let-chains).

Also, sorry `@lcnr` I know you asked for me to separate the commit where we `mv rustc_trait_selection/solve/... rustc_next_trait_solver/solve/...`, but I had already done all the work by that point. Luckily, `git` understands the file moves so it should still be relatively reviewable.

If this is still very difficult to review, then I can do some rebasing magic to try to separate this out. Please let me know!

r? lcnr
2024-06-18 19:41:33 +00:00
Oli Scherer
3f34196839 Remove redundant argument from subdiagnostic method 2024-06-18 15:42:11 +00:00
Michael Goulet
7d2be888b6 Fix impl for SolverDelegate 2024-06-18 11:04:01 -04:00
bors
12b33d36f3 Auto merge of #126540 - jhpratt:rollup-fzzz8j3, r=jhpratt
Rollup of 4 pull requests

Successful merges:

 - #125112 (Document behavior of `create_dir_all` wrt. empty path)
 - #126127 (Spell out other trait diagnostic)
 - #126309 (unify git command preperation)
 - #126539 (Update `Arc::try_unwrap()` docs)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-06-16 07:44:33 +00:00
Jacob Pratt
936d76009b
Rollup merge of #126127 - Alexendoo:other-trait-diag, r=pnkfelix
Spell out other trait diagnostic

I recently saw somebody confused about the diagnostic thinking it was suggesting to add an `as` cast. This change is longer but I think it's clearer
2024-06-16 03:41:57 -04:00
bors
5639c21fb3 Auto merge of #126505 - compiler-errors:no-vtable, r=lcnr
Only compute vtable information during codegen

This PR removes vtable information from the `Object` and `TraitUpcasting` candidate sources in the trait solvers, and defers the computation of relevant information to `Instance::resolve`. This is because vtables really aren't a thing in the trait world -- they're an implementation detail in codegen.

Previously it was just easiest to tangle this information together since we were already doing the work of looking at all the supertraits in the trait solver, and specifically because we use traits to represent when it's possible to call a method via a vtable (`Object` candidate) and do upcasting (`Unsize` candidate). but I am somewhat suspicious we're doing a *lot* of extra work, especially in polymorphic contexts, so let's see what perf says.
2024-06-16 05:33:49 +00:00
许杰友 Jieyou Xu (Joe)
ea2ac347f0 trait_selection: remove extra words 2024-06-15 15:50:00 +00:00
Matthias Krüger
6f21da3bb4
Rollup merge of #126471 - oli-obk:filter_loop, r=compiler-errors
Use a consistent way to filter out bounds instead of splitting it into three places

just a small cleanup, no logic change.

Initially the code had me looking for why anything was special here, only to realize there's nothing interesting going on
2024-06-15 10:56:42 +02:00
Michael Goulet
3b9adbec32 Only compute vtable information during codegen 2024-06-14 20:35:45 -04:00
Michael Goulet
93ff86ed7c Use is_lang_item more aggressively 2024-06-14 16:54:29 -04:00
Michael Goulet
d5c48ebc71 Add TyCtxt::is_lang_item 2024-06-14 16:50:07 -04:00
Oli Scherer
5c8bb678d0 Use a consistent way to filter out bounds instead of splitting it into three places 2024-06-14 09:40:44 +00:00
Michael Goulet
d3812ac95f LangItem-ify Coroutine trait in solvers 2024-06-13 09:34:28 -04:00
Jubilee
f6cc226f09
Rollup merge of #126353 - compiler-errors:move-match, r=lcnr
Move `MatchAgainstFreshVars` to old solver

Small change I noticed when trying to uplift the relations to the new trait solver.
2024-06-12 20:03:21 -07:00
Jubilee
25c55c51cb
Rollup merge of #126142 - compiler-errors:trait-ref-split, r=jackh726
Harmonize using root or leaf obligation in trait error reporting

When #121826 changed the error reporting to use root obligation and not the leafmost obligation, it didn't actually make sure that all the other diagnostics helper functions used the right obligation.

Specifically, when reporting similar impl candidates we are looking for impls of the root obligation, but trying to match them against the trait ref of the leaf obligation.

This does a few other miscellaneous changes. There's a lot more clean-up that could be done here, but working with this code is really grief-inducing due to how messy it has become over the years. Someone really needs to show it love. 😓

r? ``@estebank``

Fixes #126129
2024-06-12 20:03:19 -07:00
Michael Goulet
ae24ebe710 Rebase fallout 2024-06-12 21:17:33 -04:00
Michael Goulet
2c0348a0d8 Stop passing traitref/traitpredicate by ref 2024-06-12 20:57:24 -04:00
Michael Goulet
f8d12d9189 Stop passing both trait pred and trait ref 2024-06-12 20:57:23 -04:00
Michael Goulet
c453c82de4 Harmonize use of leaf and root obligation in trait error reporting 2024-06-12 20:57:23 -04:00
Michael Goulet
b0c1474381 better error message for normalizes-to ambiguities 2024-06-12 19:03:37 -04:00
Michael Goulet
4b809b9438 Move MatchAgainstFreshVars to old solver 2024-06-12 16:24:05 -04:00
Alex Macleod
d0112c6849 Spell out other trait diagnostic 2024-06-12 12:34:47 +00:00
Jubilee
519a322392
Rollup merge of #126187 - surechen:fix_125997, r=oli-obk
For E0277 suggest adding `Result` return type for function when using QuestionMark `?` in the body.

Adding suggestions for following function in E0277.

```rust
fn main() {
    let mut _file = File::create("foo.txt")?;
}
```

to

```rust
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut _file = File::create("foo.txt")?;

    return Ok(());
}
```

According to the issue #125997, only the code examples in the issue are targeted, but the issue covers a wider range of situations.

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->
2024-06-12 03:57:20 -07:00
bors
76c73827dc Auto merge of #126130 - compiler-errors:goal-relations, r=lcnr
Make `ObligationEmittingRelation`s emit `Goal` rather than `Obligation`

Helps avoid needing to uplift `Obligation` into the solver. We still can't get rid of `ObligationCause`, but we can keep it as an associated type for `InferCtxtLike` and just give it a `dummy` function.

There's some shuttling between `Goal` and `Obligation` that may be perf-sensitive... Let's see what rust-timer says.

r? lcnr
2024-06-12 03:35:31 +00:00
surechen
0b3fec9388 For E0277 suggest adding Result return type for function which using QuesionMark ? in the body. 2024-06-12 11:33:22 +08:00
许杰友 Jieyou Xu (Joe)
12358a7363
Rollup merge of #126055 - lengrongfu:master, r=pnkfelix
Expand list of trait implementers in E0277 when calling rustc with --verbose

Fixes: https://github.com/rust-lang/rust/issues/125984

- Build `rustc` use `./x build`.
- Test result
<img width="634" alt="image" src="https://github.com/rust-lang/rust/assets/15009201/89377059-2316-492b-a38a-fa33adfc9793">

- vim test.rs
```rust
trait Reconcile {
    fn reconcile(&self);
}

// Implementing the trait for some types
impl Reconcile for bool {
    fn reconcile(&self) {
        println!("Reconciling bool");
    }
}

impl Reconcile for i8 {
    fn reconcile(&self) {
        println!("Reconciling i8");
    }
}

impl Reconcile for i16 {
    fn reconcile(&self) {
        println!("Reconciling i16");
    }
}

impl Reconcile for i32 {
    fn reconcile(&self) {
        println!("Reconciling i32");
    }
}

impl Reconcile for i64 {
    fn reconcile(&self) {
        println!("Reconciling i64");
    }
}

impl Reconcile for u8 {
    fn reconcile(&self) {
        println!("Reconciling u8");
    }
}

impl Reconcile for u16 {
    fn reconcile(&self) {
        println!("Reconciling u16");
    }
}

impl Reconcile for u32 {
    fn reconcile(&self) {
        println!("Reconciling u32");
    }
}

impl Reconcile for i128 {
    fn reconcile(&self) {
        println!("Reconciling u32");
    }
}

impl Reconcile for u128 {
    fn reconcile(&self) {
        println!("Reconciling u32");
    }
}

fn process<T: Reconcile>(item: T) {
    item.reconcile();
}

fn main() {
    let value = String::from("This will cause an error");
    process(value); // This line will cause a compilation error
}
```
2024-06-11 21:27:47 +01:00
Michael Goulet
4038010436 Get rid of PredicateObligations 2024-06-11 13:52:51 -04:00
许杰友 Jieyou Xu (Joe)
2a94a5bc21
Rollup merge of #126258 - oli-obk:recursive_rpit, r=lcnr
Do not define opaque types when selecting impls

fixes #126117

r? `@lcnr` for inconsistency with next solver
2024-06-11 14:16:47 +01:00
Oli Scherer
6cca6da126 Revert "When checking whether an impl applies, constrain hidden types of opaque types."
This reverts commit 29a630eb72.
2024-06-11 08:08:25 +00:00
Michael Goulet
4b188d9d66 Only compute specializes query if specialization is enabled in the crate of the specialized impl 2024-06-07 15:58:50 -04:00
Michael Goulet
91274c84b9 Uplift TypeRelation and Relate 2024-06-06 07:50:19 -04:00
Michael Goulet
82ef3ad980 Uplift TypeError 2024-06-06 07:49:47 -04:00
bors
003a902792 Auto merge of #125958 - BoxyUwU:remove_const_ty, r=lcnr
Remove the `ty` field from type system `Const`s

Fixes #125556
Fixes #122908

Part of the work on `adt_const_params`/`generic_const_param_types`/`min_generic_const_exprs`/generally making the compiler nicer. cc rust-lang/project-const-generics#44

Please review commit-by-commit otherwise I wasted a lot of time not just squashing this into a giant mess (and also it'll be SO much nicer because theres a lot of fluff changes mixed in with other more careful changes if looking via File Changes

---

Why do this?
- The `ty` field keeps causing ICEs and weird behaviour due to it either being treated as "part of the const" or it being forgotten about leading to ICEs.
- As we move forward with `adt_const_params` and a potential `min_generic_const_exprs` it's going to become more complex to actually lower the correct `Ty<'tcx>`
- It muddles the idea behind how we check `Const` arguments have the correct type. By having the `ty` field it may seem like we ought to be relating it when we relate two types, or that its generally important information about the `Const`.
- Brings the compiler more in line with `a-mir-formality` as that also tracks the type of type system `Const`s via `ConstArgHasType` bounds in the env instead of on the `Const` itself.
- A lot of stuff is a lot nicer when you dont have to pass around the type of a const lol. Everywhere we construct `Const` is now significantly nicer 😅

See #125671's description for some more information about the `ty` field

---

General summary of changes in this PR:

- Add `Ty` to `ConstKind::Value` as otherwise there is no way to implement `ConstArgHasType` to ensure that const arguments are correctly typed for the parameter when we stop creating anon consts for all const args. It's also just incredibly difficult/annoying to thread the correct `Ty` around to a bunch of ctfe functions otherwise.
-  Fully implement `ConstArgHasType` in both the old and new solver. Since it now has no reliance on the `ty` field it serves its originally intended purpose of being able to act as a double check that trait vs impls have correctly typed const parameters. It also will now be able to be responsible for checking types of const arguments to parameters under `min_generic_const_exprs`.
- Add `Ty` to `mir::Const::Ty`. I dont have a great understanding of why mir constants are setup like this to be honest. Regardless they need to be able to determine the type of the const and the easiest way to make this happen was to simply store the `Ty` along side the `ty::Const`. Maybe we can do better here in the future but I'd have to spend way more time looking at everywhere we use `mir::Const`.
- rustdoc has its own `Const` which also has a `ty` field. It was relatively easy to remove this.

---

r? `@lcnr` `@compiler-errors`
2024-06-06 03:41:23 +00:00
rongfu.leng
69769fc797 Expand list of trait implementers in E0277 when calling rustc with --verbose
Signed-off-by: rongfu.leng <lenronfu@gmail.com>
2024-06-06 09:38:09 +08:00
Boxy
8d6705cdb8 Fully implement ConstArgHasType 2024-06-05 22:25:41 +01:00
Boxy
a9702a6668 Add Ty to ConstKind::Value 2024-06-05 22:25:41 +01:00
Boxy
58feec9b85 Basic removal of Ty from places (boring) 2024-06-05 22:25:38 +01:00
bors
72fdf913c5 Auto merge of #126038 - matthiaskrgr:rollup-h4rm3x2, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #124840 (resolve: mark it undetermined if single import is not has any bindings)
 - #125622 (Winnow private method candidates instead of assuming any candidate of the right name will apply)
 - #125648 (Remove unused(?) `~/rustsrc` folder from docker script)
 - #125672 (Add more ABI test cases to miri (RFC 3391))
 - #125800 (Fix `mut` static task queue in SGX target)
 - #125871 (Orphanck[old solver]: Consider opaque types to never cover type parameters)
 - #125893 (Handle all GVN binops in a single place.)
 - #126008 (Port `tests/run-make-fulldeps/issue-19371` to ui-fulldeps)
 - #126032 (Update description of the `IsTerminal` example)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-06-05 20:53:32 +00:00
Matthias Krüger
9c8e46d08a
Rollup merge of #125871 - fmease:fix-orphanck-opaques, r=lcnr
Orphanck[old solver]: Consider opaque types to never cover type parameters

This fixes an oversight of mine in #117164. The change itself has already been FCP'ed.

This only affects the old solver, the next solver already correctly rejects the added test since #117164.

r? ``@lcnr``
2024-06-05 18:21:14 +02:00
Matthias Krüger
e1745122ae
Rollup merge of #125792 - compiler-errors:dont-drop-upcast-cand, r=lcnr
Don't drop `Unsize` candidate in intercrate mode

Fixes #125767
2024-06-05 18:21:09 +02:00
León Orell Valerian Liehr
874670399c
Orphanck: Consider opaque types to never cover type parameters 2024-06-04 18:57:19 +02:00
Michael Goulet
46a033958a
Rollup merge of #125717 - weiznich:move/do_not_recommend_to_diganostic_namespace, r=compiler-errors
Refactor `#[diagnostic::do_not_recommend]` support

This commit refactors the `#[do_not_recommend]` support in the old parser to also apply to projection errors and not only to selection errors. This allows the attribute to be used more widely.

Part of #51992

r? `@compiler-errors`

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->
2024-06-04 08:52:12 -04:00
许杰友 Jieyou Xu (Joe)
b477f89041
Rollup merge of #125750 - compiler-errors:expect, r=lcnr
Align `Term` methods with `GenericArg` methods, add `Term::expect_*`

* `Term::ty` -> `Term::as_type`.
* `Term::ct` -> `Term::as_const`.
* Adds `Term::expect_type` and `Term::expect_const`, and uses them in favor of `.ty().unwrap()`, etc.

I could also shorten these to `as_ty` and then do `GenericArg::as_ty` as well, but I do think the `as_` is important to signal that this is a conversion method, and not a getter, like `Const::ty` is.

r? types
2024-06-04 08:25:48 +01:00
bors
90d6255d82 Auto merge of #125380 - compiler-errors:wc-obj-safety, r=oli-obk
Make `WHERE_CLAUSES_OBJECT_SAFETY` a regular object safety violation

#### The issue

In #50781, we have known about unsound `where` clauses in function arguments:

```rust
trait Impossible {}

trait Foo {
    fn impossible(&self)
    where
        Self: Impossible;
}

impl Foo for &() {
    fn impossible(&self)
    where
        Self: Impossible,
    {}
}

// `where` clause satisfied for the object, meaning that the function now *looks* callable.
impl Impossible for dyn Foo {}

fn main() {
    let x: &dyn Foo = &&();
    x.impossible();
}
```

... which currently segfaults at runtime because we try to call a method in the vtable that doesn't exist. :(

#### What did u change

This PR removes the `WHERE_CLAUSES_OBJECT_SAFETY` lint and instead makes it a regular object safety violation. I choose to make this into a hard error immediately rather than a `deny` because of the time that has passed since this lint was authored, and the single (1) regression (see below).

That means that it's OK to mention `where Self: Trait` where clauses in your trait, but making such a trait into a `dyn Trait` object will report an object safety violation just like `where Self: Sized`, etc.

```rust
trait Impossible {}

trait Foo {
    fn impossible(&self)
    where
        Self: Impossible; // <~ This definition is valid, just not object-safe.
}

impl Foo for &() {
    fn impossible(&self)
    where
        Self: Impossible,
    {}
}

fn main() {
    let x: &dyn Foo = &&(); // <~ THIS is where we emit an error.
}
```

#### Regressions

From a recent crater run, there's only one crate that relies on this behavior: https://github.com/rust-lang/rust/pull/124305#issuecomment-2122381740. The crate looks unmaintained and there seems to be no dependents.

#### Further

We may later choose to relax this (e.g. when the where clause is implied by the supertraits of the trait or something), but this is not something I propose to do in this FCP.

For example, given:

```
trait Tr {
  fn f(&self) where Self: Blanket;
}

impl<T: ?Sized> Blanket for T {}
```

Proving that some placeholder `S` implements `S: Blanket` would be sufficient to prove that the same (blanket) impl applies for both `Concerete: Blanket` and `dyn Trait: Blanket`.

Repeating here that I don't think we need to implement this behavior right now.

----

r? lcnr
2024-06-04 02:34:20 +00:00
Michael Goulet
273b990554 Align Term methods with GenericArg methods 2024-06-03 20:36:27 -04:00
Michael Goulet
a41c44f21c Nits and formatting 2024-06-03 10:02:08 -04:00
Michael Goulet
511f1cf7c8 check_is_object_safe -> is_object_safe 2024-06-03 09:49:30 -04:00
Michael Goulet
de6b219803 Make WHERE_CLAUSES_OBJECT_SAFETY a regular object safety violation 2024-06-03 09:49:04 -04:00
Michael Goulet
1e72c7f536 Add cycle errors to ScrubbedTraitError to remove a couple more calls to new_with_diagnostics 2024-06-03 09:27:52 -04:00
Michael Goulet
27f5eccd1f Move FulfillmentErrorCode to rustc_trait_selection too 2024-06-03 09:27:52 -04:00
Michael Goulet
94a524ed11 Use ScrubbedTraitError in more places 2024-06-03 09:27:52 -04:00
Michael Goulet
eb0a70a557 Opt-in diagnostics reporting to avoid doing extra work in the new solver 2024-06-03 09:27:52 -04:00
Michael Goulet
54b2b7d460 Make TraitEngines generic over error 2024-06-03 09:27:52 -04:00
Michael Goulet
084ccd2390 Remove unnecessary extension trait 2024-06-03 09:27:52 -04:00
bors
1d52972dd8 Auto merge of #125778 - estebank:issue-67100, r=compiler-errors
Use parenthetical notation for `Fn` traits

Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`.

Address #67100:

```
error[E0277]: expected a `Fn()` closure, found `F`
 --> file.rs:6:13
  |
6 |     call_fn(f)
  |     ------- ^ expected an `Fn()` closure, found `F`
  |     |
  |     required by a bound introduced by this call
  |
  = note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `call_fn`
 --> file.rs:1:15
  |
1 | fn call_fn<F: Fn() -> ()>(f: &F) {
  |               ^^^^^^^^^^ required by this bound in `call_fn`
help: consider further restricting this bound
  |
5 | fn call_any<F: std::any::Any + Fn()>(f: &F) {
  |                              ++++++
```
2024-06-03 08:14:03 +00:00
bors
0038c02103 Auto merge of #125775 - compiler-errors:uplift-closure-args, r=lcnr
Uplift `{Closure,Coroutine,CoroutineClosure}Args` and friends to `rustc_type_ir`

Part of converting the new solver's `structural_traits.rs` to be interner-agnostic.

I decided against aliasing `ClosureArgs<TyCtxt<'tcx>>` to `ClosureArgs<'tcx>` because it seemed so rare. I could do so if desired, though.

r? lcnr
2024-06-01 19:07:03 +00:00
Michael Goulet
333458c2cb Uplift TypeRelation and Relate 2024-06-01 12:50:58 -04:00
Mark Rousskov
95e073234f Deduplicate supertrait_def_ids code 2024-06-01 07:50:32 -04:00
Mark Rousskov
dd9c8cc467 Increase vtable layout size
This improves LLVM's codegen by allowing vtable loads to be hoisted out
of loops (as just one example).
2024-06-01 07:42:05 -04:00
bors
99cb42c296 Auto merge of #124662 - zetanumbers:needs_async_drop, r=oli-obk
Implement `needs_async_drop` in rustc and optimize async drop glue

This PR expands on #121801 and implements `Ty::needs_async_drop` which works almost exactly the same as `Ty::needs_drop`, which is needed for #123948.

Also made compiler's async drop code to look more like compiler's regular drop code, which enabled me to write an optimization where types which do not use `AsyncDrop` can simply forward async drop glue to `drop_in_place`. This made size of the async block from the [async_drop test](67980dd6fb/tests/ui/async-await/async-drop.rs) to decrease by 12%.
2024-05-31 10:12:24 +00:00
Matthias Krüger
379233242b
Rollup merge of #125635 - fmease:mv-type-binding-assoc-item-constraint, r=compiler-errors
Rename HIR `TypeBinding` to `AssocItemConstraint` and related cleanup

Rename `hir::TypeBinding` and `ast::AssocConstraint` to `AssocItemConstraint` and update all items and locals using the old terminology.

Motivation: The terminology *type binding* is extremely outdated. "Type bindings" not only include constraints on associated *types* but also on associated *constants* (feature `associated_const_equality`) and on RPITITs of associated *functions* (feature `return_type_notation`). Hence the word *item* in the new name. Furthermore, the word *binding* commonly refers to a mapping from a binder/identifier to a "value" for some definition of "value". Its use in "type binding" made sense when equality constraints (e.g., `AssocTy = Ty`) were the only kind of associated item constraint. Nowadays however, we also have *associated type bounds* (e.g., `AssocTy: Bound`) for which the term *binding* doesn't make sense.

---

Old terminology (HIR, rustdoc):

```
`TypeBinding`: (associated) type binding
├── `Constraint`: associated type bound
└── `Equality`: (associated) equality constraint (?)
    ├── `Ty`: (associated) type binding
    └── `Const`: associated const equality (constraint)
```

Old terminology (AST, abbrev.):

```
`AssocConstraint`
├── `Bound`
└── `Equality`
    ├── `Ty`
    └── `Const`
```

New terminology (AST, HIR, rustdoc):

```
`AssocItemConstraint`: associated item constraint
├── `Bound`: associated type bound
└── `Equality`: associated item equality constraint OR associated item binding (for short)
    ├── `Ty`: associated type equality constraint OR associated type binding (for short)
    └── `Const`: associated const equality constraint OR associated const binding (for short)
```

r? compiler-errors
2024-05-31 08:50:22 +02:00
Michael Goulet
e485b193d0 Don't drop Upcast candidate in intercrate mode 2024-05-30 19:45:59 -04:00
León Orell Valerian Liehr
34c56c45cf
Rename HIR TypeBinding to AssocItemConstraint and related cleanup 2024-05-30 22:52:33 +02:00
bors
d43930dab3 Auto merge of #125711 - oli-obk:const_block_ice2, r=Nadrieril
Make `body_owned_by` return the `Body` instead of just the `BodyId`

fixes #125677

Almost all `body_owned_by` callers immediately called `body`, too, so just return `Body` directly.

This makes the inline-const query feeding more robust, as all calls to `body_owned_by` will now yield a body for inline consts, too.

I have not yet figured out a good way to make `tcx.hir().body()` return an inline-const body, but that can be done as a follow-up
2024-05-30 08:00:11 +00:00
bors
32a3ed229c Auto merge of #125671 - BoxyUwU:remove_const_ty_eq, r=compiler-errors
Do not equate `Const`'s ty in `super_combine_const`

Fixes #114456

In #125451 we started relating the `Const`'s tys outside of a probe so it was no longer simply an assertion to catch bugs.

This was done so that when we _do_ provide a wrongly typed const argument to an item if we wind up relating it with some other instantiation we'll have a `TypeError` we can bubble up and taint the resulting mir allowing const eval to skip evaluation.

In this PR I instead change `ConstArgHasType` to correctly handle checking the types of const inference variables. Previously if we had something like `impl<const N: u32> Trait for [(); N]`, when using the impl we would instantiate it with infer vars and then check that `?x: u32` is of type `u32` and succeed. Then later we would infer `?x` to some `Const` of type `usize`.

We now stall on `?x` in `ConstArgHasType` until it has a concrete value that we can determine the type of. This allows us to fail using the erroneous implementation of `Trait` which allows us to taint the mir.

Long term we intend to remove the `ty` field on `Const` so we would have no way of accessing the `ty` of a const inference variable anyway and would have to do this. I did not fully update `ConstArgHasType` to avoid using the `ty` field as it's not entirely possible right now- we would need to lookup `ConstArgHasType` candidates in the env.

---

As for _why_ I think we should do this, relating the types of const's is not necessary for soundness of the type system. Originally this check started off as a plain `==` in `super_relate_consts` and gradually has been growing in complexity as we support more complicated types. It was never actually required to ensure that const arguments are correctly typed for their parameters however.

The way we currently check that a const argument has the correct type is a little convoluted and confusing (and will hopefully be less weird as time goes on). Every const argument has an anon const with its return type set to type of the const parameter it is an argument to. When type checking the anon const regular type checking rules require that the expression is the same type as the return type. This effectively ensure that no matter what every const argument _always_ has the correct type.

An extra bit of complexity is that during `hir_ty_lowering` we do not represent everything as a `ConstKind::Unevaluated` corresponding to the anon const. For generic parameters i.e. `[(); N]` we simply represent them as `ConstKind::Param` as we do not want `ConstKind::Unevaluated` with generic substs on stable under min const generics. The anon const still gets type checked resulting in errors about type mismatches.

Eventually we intend to not create anon consts for all const arguments (for example for `ConstKind::Param`) and instead check that the argument type is correct via `ConstArgHasType` obligations (these effectively also act as a check that the anon consts have the correctly set return type).

What this all means is that the the only time we should ever have mismatched types when relating two `Const`s is if we have messed up our logic for ensuring that const arguments are of the correct type. Having this not be an assert is:
- Confusing as it may incorrectly lead people to believe this is an important check that is actually required
- Opens the possibility for bugs or behaviour reliant on this (unnecessary) check existing

---

This PR makes two tests go from pass->ICE (`generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs` and `tests/crashes/121858.rs`). This is caused by the fact that we evaluate anon consts even if their where clauses do not hold and is a pre-existing issue and only affects `generic_const_exprs`. I am comfortable exposing the brokenness of `generic_const_exprs` more with this PR

This PR makes a test go from ICE->pass (`const-generics/issues/issue-105821.rs`). I have no idea why this PR affects that but I believe that ICE is an unrelated issue to do with the fact that under `generic_const_exprs`/`adt_const_params` we do not handle lifetimes in const parameter types correctly. This PR is likely just masking this bug.

Note: this PR doesn't re-introduce the assertion that the two consts' tys are equal. I'm not really sure how I feel about this but tbh it has caused more ICEs than its found lately so 🤷‍♀️

r? `@oli-obk` `@compiler-errors`
2024-05-30 05:50:44 +00:00
Esteban Küber
e6bd6c2044 Use parenthetical notation for Fn traits
Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`.

Fix #67100:

```
error[E0277]: expected a `Fn()` closure, found `F`
 --> file.rs:6:13
  |
6 |     call_fn(f)
  |     ------- ^ expected an `Fn()` closure, found `F`
  |     |
  |     required by a bound introduced by this call
  |
  = note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `call_fn`
 --> file.rs:1:15
  |
1 | fn call_fn<F: Fn() -> ()>(f: &F) {
  |               ^^^^^^^^^^ required by this bound in `call_fn`
help: consider further restricting this bound
  |
5 | fn call_any<F: std::any::Any + Fn()>(f: &F) {
  |                              ++++++
```
2024-05-29 22:26:54 +00:00