Don't check unnecessarily that impl trait is RPIT
We have this random `return_type_impl_trait` function to detect if a function returns an RPIT which is used in outlives suggestions, but removing it doesn't actually change any diagnostics. Let's just remove it.
Also, suppress a spurious outlives error from a ReError.
Fixes#114274
Map RPITIT's opaque type bounds back from projections to opaques
An RPITIT in a program's AST is eventually translated into both a projection GAT and an opaque. The opaque is used for default trait methods, like:
```
trait Foo {
fn bar() -> impl Sized { 0i32 }
}
```
The item bounds for both the projection and opaque are identical, and both have a *projection* self ty. This is mostly okay, since we can normalize this projection within the default trait method body to the opaque, but it does two things:
1. it leads to bugs in places where we don't normalize item bounds, like `deduce_future_output_from_obligations`
2. it leads to extra match arms that are both suspicious looking and also easy to miss
This PR maps the opaque type bounds of the RPITIT's *opaque* back to the opaque's self type to avoid this quirk. Then we can fix the UI test for #108304 (1.) and also remove a bunch of match arms (2.).
Fixes#108304
r? `@spastorino`
Rollup of 7 pull requests
Successful merges:
- #114099 (privacy: no nominal visibility for assoc fns )
- #114128 (When flushing delayed span bugs, write to the ICE dump file even if it doesn't exist)
- #114138 (Adjust spans correctly for fn -> method suggestion)
- #114146 (Skip reporting item name when checking RPITIT GAT's associated type bounds hold)
- #114147 (Insert RPITITs that were shadowed by missing ADTs that resolve to [type error])
- #114155 (Replace a lazy `RefCell<Option<T>>` with `OnceCell<T>`)
- #114164 (Add regression test for `--cap-lints allow` and trait bounds warning)
r? `@ghost`
`@rustbot` modify labels: rollup
Double check that hidden types match the expected hidden type
Fixes https://github.com/rust-lang/rust/issues/113278 specifically, but I left a TODO for where we should also add some hardening.
It feels a bit like papering over the issue, but at least this way we don't get unsoundness, but just surprising errors. Errors will be improved and given spans before this PR lands.
r? `@compiler-errors` `@lcnr`
Include the computed alignment of the violating field when rejecting
transparent types with non-trivially aligned ZSTs.
ZST member fields in transparent types must have an alignment of 1 (to
ensure it does not raise the layout requirements of the transparent
field). The current error message looks like this:
LL | struct Foobar(u32, [u32; 0]);
| ^^^^^^^^ has alignment larger than 1
This patch changes the report to include the alignment of the violating
field:
LL | struct Foobar(u32, [u32; 0]);
| ^^^^^^^^ has alignment of 4, which is larger than 1
In case of unknown alignments, it will yield:
LL | struct Foobar<T>(u32, [T; 0]);
| ^^^^^^ may have alignment larger than 1
This allows developers to get a better grasp why a specific field is
rejected. Knowing the alignment of the violating field makes it easier
to judge where that alignment-requirement originates, and thus hopefully
provide better hints on how to mitigate the problem.
This idea was proposed in 2022 in #98071 as part of a bigger change.
This commit simply extracts this error-message change, to decouple it
from the other diagnostic improvements.
Make it clearer that we're just checking for an RPITIT
Tiny nit to use `is_impl_trait_in_trait` more, to make it clearer that we're just checking whether a def-id is an RPITIT, rather than doing something meaningful with the `opt_rpitit_info`.
r? `@spastorino`
Various impl trait in assoc tys cleanups
r? `@compiler-errors`
All commits except for the last are pure refactorings. 274dab5bd658c97886a8987340bf50ae57900c39 allows struct fields to participate in deciding whether a function has an opaque in its signature.
best reviewed commit by commit
Add a fully fledged `Clause` type, rename old `Clause` to `ClauseKind`
Does two basic things before I put up a more delicate set of PRs (along the lines of #112714, but hopefully much cleaner) that migrate existing usages of `ty::Predicate` to `ty::Clause` (`predicates_of`/`item_bounds`/`ParamEnv::caller_bounds`).
1. Rename `Clause` to `ClauseKind`, so it's parallel with `PredicateKind`.
2. Add a new `Clause` type which is parallel to `Predicate`.
* This type exposes `Clause::kind(self) -> Binder<'tcx, ClauseKind<'tcx>>` which is parallel to `Predicate::kind` 😸
The new `Clause` type essentially acts as a newtype wrapper around `Predicate` that asserts that it is specifically a `PredicateKind::Clause`. Turns out from experimentation[^1] that this is not negative performance-wise, which is wonderful, since this a much simpler design than something that requires encoding the discriminant into the alignment bits of a predicate kind, or something else like that...
r? ``@lcnr`` or ``@oli-obk``
[^1]: https://github.com/rust-lang/rust/pull/112714#issuecomment-1595653910
Add `-Ztrait-solver=next-coherence`
Flag that conditionally uses the trait solver *only* during coherence, for more testing and/or eventual partial-migration onto the trait solver (in the medium- to long-term).
* This still uses the selection context in some of the coherence methods I think, so it's not "complete". Putting this up for review and/or for further work in-tree.
* I probably need to spend a bit more time making sure that we don't sneakily create any other infcx's during coherence that also need the new solver enabled.
r? `@lcnr`
- Switch TypeId to 128 bits
- Hack around the fact that tracing-subscriber dislikes how TypeId is hashed
- Remove lowering of type_id128 from rustc_codegen_llvm
- Remove unnecessary `type_id128` intrinsic (just change return type of `type_id`)
- Only hash the lower 64 bits of the TypeId
- Reword comment
`EarlyBinder::new` -> `EarlyBinder::bind`
for consistency with `Binder::bind`. it may make sense to also add `EarlyBinder::dummy` in places where we know that no parameters exist, but I left that out of this PR.
r? `@jackh726` `@kylematsuda`
Each of `{D,Subd}iagnosticMessage::{Str,Eager}` has a comment:
```
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
```
This commit answers that question in the affirmative. It's not the most
compelling change ever, but it might be worth merging.
This requires changing the `impl<'a> From<&'a str>` impls to `impl
From<&'static str>`, which involves a bunch of knock-on changes that
require/result in call sites being a little more precise about exactly
what kind of string they use to create errors, and not just `&str`. This
will result in fewer unnecessary allocations, though this will not have
any notable perf effects given that these are error paths.
Note that I was lazy within Clippy, using `to_string` in a few places to
preserve the existing string imprecision. I could have used `impl
Into<{D,Subd}iagnosticMessage>` in various places as is done in the
compiler, but that would have required changes to *many* call sites
(mostly changing `&format("...")` to `format!("...")`) which didn't seem
worthwhile.
Handle error body in generator layout
Fixes#111468
I feel like making this query return `Option<GeneratorLayout>` might be better but had some issues with that approach
use implied bounds when checking opaque types
During opaque type inference, we check for the well-formedness of the hidden type in the opaque type's own environment, not the one of the defining site, which are different in the case of TAIT.
However in the case of associated-type-impl-trait, we don't use implied bounds from the impl header. This caused us to reject the following:
```rust
trait Service<Req> {
type Output;
fn call(req: Req) -> Self::Output;
}
impl<'a, Req> Service<&'a Req> for u8 {
type Output= impl Sized; // we can't prove WF of hidden type `WF(&'a Req)` although it's implied by the impl
//~^ ERROR type parameter Req doesn't live long enough
fn call(req: &'a Req) -> Self::Output {
req
}
}
```
although adding an explicit bound would make it pass:
```diff
- impl<'a, Req> Service<&'a Req> for u8 {
+ impl<'a, Req> Service<&'a Req> for u8 where Req: 'a, {
```
I believe it should pass as we already allow the concrete type to be used:
```diff
impl<'a, Req> Service<&'a Req> for u8 {
- type Output= impl Sized;
+ type Output= &'a Req;
```
Fixes#95922
Builds on #105982
cc ``@lcnr`` (because implied bounds)
r? ``@oli-obk``
enable `rust_2018_idioms` lint group for doctests
With this change, `rust_2018_idioms` lint group will be enabled for compiler/libstd doctests.
Resolves#106086Resolves#99144
Signed-off-by: ozkanonur <work@onurozkan.dev>
Explicitly reject negative and reservation drop impls
Fixes#110858
It doesn't really make sense for a type to have a `!Drop` impl. Or at least, I don't want us to implicitly assign a meaning to it by the way the compiler *currently* handles it (incompletely), and rather I would like to see a PR (or an RFC...) assign a meaning to `!Drop` if we actually wanted one for it.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
Use MIR's `Offset` for pointer `add` too
~~Status: draft while waiting for #110822 to land, since this is built atop that.~~
~~r? `@ghost~~`
Canonical Rust code has mostly moved to `add`/`sub` on pointers, which take `usize`, instead of `offset` which takes `isize`. (And, relatedly, when `sub_ptr` was added it turned out it replaced every single in-tree use of `offset_from`, because `usize` is just so much more useful than `isize` in Rust.)
Unfortunately, `intrinsics::offset` could only accept `*const` and `isize`, so there's a *huge* amount of type conversions back and forth being done. They're identity conversions in the backend, but still end up producing quite a lot of unhelpful MIR.
This PR changes `intrinsics::offset` to accept `*const` *and* `*mut` along with `isize` *and* `usize`. Conveniently, the backends and CTFE already handle this, since MIR's `BinOp::Offset` [already supports all four combinations](adaac6b166/compiler/rustc_const_eval/src/transform/validate.rs (L523-L528)).
To demonstrate the difference, I added some `mir-opt/pre-codegen/` tests around slice indexing. Here's the difference to `[T]::get_mut`, since it uses `<*mut _>::add` internally:
```diff
`@@` -79,30 +70,21 `@@` fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
StorageLive(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
StorageLive(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
_9 = _8 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageLive(_13); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _13 = _2 as isize (IntToInt); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageLive(_14); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageLive(_15); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _15 = _9 as *const u32 (Pointer(MutToConstPointer)); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _14 = Offset(move _15, _13); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageDead(_15); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _7 = move _14 as *mut u32 (PtrToPtr); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageDead(_14); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageDead(_13); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+ _7 = Offset(_9, _2); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
StorageDead(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
StorageDead(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
StorageDead(_11); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
```
1c1c8e442a (diff-a841b6a4538657add3f39bc895744331453d0625e7aace128b1f604f0b63c8fdR80)
Add lint to deny diagnostics composed of static strings
r? ghost
I'm hoping to have a lint that semi-automatically converts simple diagnostics such as `struct_span_err(span, "msg").help("msg").span_note(span2, "msg").emit()` to typed session diagnostics. It's quite hacky and not entirely working because of problems with `x fix` but should hopefully help reduce some of the work.
I'm going to start trying to apply what I can from this, but opening this as a draft in case anyone wants to develop on it.
cc #100717
Switch to `EarlyBinder` for `explicit_item_bounds`
Part of the work to finish https://github.com/rust-lang/rust/issues/105779.
This PR adds `EarlyBinder` to the return type of the `explicit_item_bounds` query and removes `bound_explicit_item_bounds`.
r? `@compiler-errors` (hope it's okay to request you, since you reviewed #110299 and #110498😃)
Add `intrinsics::transmute_unchecked`
This takes a whole 3 lines in `compiler/` since it lowers to `CastKind::Transmute` in MIR *exactly* the same as the existing `intrinsics::transmute` does, it just doesn't have the fancy checking in `hir_typeck`.
Added to enable experimenting with the request in <https://github.com/rust-lang/rust/pull/106281#issuecomment-1496648190> and because the portable-simd folks might be interested for dependently-sized array-vector conversions.
It also simplifies a couple places in `core`.
See also https://github.com/rust-lang/rust/pull/108442#issuecomment-1474777273, where `CastKind::Transmute` was added having exactly these semantics before the lang meeting (which I wasn't in) independently expressed interest.
This takes a whole 3 lines in `compiler/` since it lowers to `CastKind::Transmute` in MIR *exactly* the same as the existing `intrinsics::transmute` does, it just doesn't have the fancy checking in `hir_typeck`.
Added to enable experimenting with the request in <https://github.com/rust-lang/rust/pull/106281#issuecomment-1496648190> and because the portable-simd folks might be interested for dependently-sized array-vector conversions.
It also simplifies a couple places in `core`.
Substitute missing trait items suggestion correctly
Properly substitute missing item suggestions, so that when they reference generics from their parent trait they actually have the right time for the impl.
Also, some other minor tweaks like using `/* Type */` to signify a GAT's type is actually missing, and fixing generic arg suggestions for GATs in general.
- require `TypeErrCtxt` to always result in an error
- move `resolve_regions_and_report_errors` to the `ObligationCtxt`
- merge `process_registered_region_obligations` into `resolve_regions`
Make elaboration generic over input
Combines all the `elaborate_*` family of functions into just one, which is an iterator over the same type that you pass in (e.g. elaborating `Predicate` gives `Predicate`s, elaborating `Obligation`s gives `Obligation`s, etc.)
And while doing the updates for that, also uses `FieldIdx` in `ProjectionKind::Field` and `TypeckResults::field_indices`.
There's more places that could use it (like `rustc_const_eval` and `LayoutS`), but I tried to keep this PR from exploding to *even more* places.
Part 2/? of https://github.com/rust-lang/compiler-team/issues/606
Correctly substitute GAT's type used in `normalize_param_env` in `check_type_bounds`
Given:
```rust
trait Foo {
type Assoc<T>: PartialEq<Self::Assoc<i32>>;
}
impl Foo for () {
type Assoc<T> = Wrapper<T>;
}
struct Wrapper<T>(T);
impl<T> PartialEq<Wrapper<i32>> for Wrapper<T> { }
```
We add an additional predicate in the `normalize_param_env` in `check_type_bounds` that is used to normalize the GAT's bounds to check them in the impl. Problematically, though, that predicate is constructed to be `for<^0> <() as Foo>::Assoc<^0> => Wrapper<T>`, instead of `for<^0> <() as Foo>::Assoc<^0> => Wrapper<^0>`.
That means `Self::Assoc<i32>` in the bounds that we're checking normalizes to `Wrapper<T>`, instead of `Wrapper<i32>`, and so the bound `Self::Assoc<T>: PartialEq<Self::Assoc<i32>>` normalizes to `Wrapper<T>: PartialEq<Wrapper<T>>`, which does not hold.
Fixes this by properly substituting the RHS of that normalizes predicate that we add to the `normalize_param_env`. That means the bound is properly normalized to `Wrapper<T>: PartialEq<Wrapper<i32>>`, which *does* hold.
---
The second commit in this PR just cleans up some substs stuff and some naming.
r? `@jackh726` cc #87900
Do not consider synthesized RPITITs on missing items checks
Without this patch for `tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs` we get ...
```
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs:4:12
|
4 | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0046]: not all trait items implemented, missing: `foo`, ``
--> tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs:12:1
|
8 | fn foo(&self) -> impl Sized;
| ----------------------------
| | |
| | `` from trait
| `foo` from trait
...
12 | impl MyTrait for i32 {
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `` in implementation
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0046`.
```
instead of ...
```
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/dont-project-to-rpitit-with-no-value.rs:4:12
|
LL | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/dont-project-to-rpitit-with-no-value.rs:12:1
|
LL | fn foo(&self) -> impl Sized;
| ---------------------------- `foo` from trait
...
LL | impl MyTrait for i32 {
| ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0046`.
```
r? `@compiler-errors`
move Option::as_slice to intrinsic
````@scottmcm```` suggested on #109095 I use a direct approach of unpacking the operation in MIR lowering, so here's the implementation.
cc ````@nikic```` as this should hopefully unblock #107224 (though perhaps other changes to the prior implementation, which I left for bootstrapping, are needed).
a general type system cleanup
removes the helper functions `traits::fully_solve_X` as they add more complexity then they are worth. It's confusing which of these helpers should be used in which context.
changes the way we deal with overflow to always add depth in `evaluate_predicates_recursively`. It may make sense to actually fully transition to not have `recursion_depth` on obligations but that's probably a bit too much for this PR.
also removes some other small - and imo unnecessary - helpers.
r? types