The recently landed PR to adjust arbitrary self types was a bit
overenthusiastic, advising folks to use the new Receiver trait even
before it's been stabilized. Revert to the older wording of the lint in
such cases.
Arbitrary self types v2: main compiler changes
This is the main PR in a series of PRs related to Arbitrary Self Types v2, tracked in #44874. Specifically this is step 7 of the plan [described here](https://github.com/rust-lang/rust/issues/44874#issuecomment-2122179688), for [RFC 3519](https://github.com/rust-lang/rfcs/pull/3519).
Overall this PR:
* Switches from the `Deref` trait to the new `Receiver` trait when the unstable `arbitrary_self_types` feature is enabled (the simple bit)
* Introduces new algorithms to spot "shadowing"; that is, the case where a newly-added method in an outer smart pointer might end up overriding a pre-existing method in the pointee (the complex bit). Most of this bit was explored in [this earlier perf-testing PR](https://github.com/rust-lang/rust/pull/127812#issuecomment-2236911900).
* Lots of tests
This should not break compatibility for:
* Stable users, where it should have no effect
* Users of the existing `arbitrary_self_types` feature (because we implement `Receiver` for `T: Deref`) _unless_ those folks have added methods which may shadow methods in inner types, which we no longer want to allow
Subsequent PRs will add better diagnostics.
It's probably easiest to review this commit-by-commit.
r? `@wesleywiser`
Some asm! diagnostic adjustments and a papercut fix
Best reviewed commit by commit.
We forgot a `normalize` call in intrinsic checking, causing us to allow literal integers, but not named constants containing that literal. This can in theory affect stable code, but only if libstd contains a stable SIMD type that has an array length that is a named constant. I'd assume we'd have noticed by now due to asm! rejecting those outright.
The error message left me scratching my head for a bit, so I added some extra information to the diagnostic, too.
In this new version of Arbitrary Self Types, we no longer use the Deref trait
exclusively when working out which self types are valid. Instead, we follow a
chain of Receiver traits. This enables methods to be called on smart pointer
types which fundamentally cannot support Deref (for instance because they are
wrappers for pointers that don't follow Rust's aliasing rules).
This includes:
* Changes to tests appropriately
* New tests for:
* The basics of the feature
* Ensuring lifetime elision works properly
* Generic Receivers
* A copy of the method subst test enhanced with Receiver
This is really the heart of the 'arbitrary self types v2' feature, and
is the most critical commit in the current PR.
Subsequent commits are focused on:
* Detecting "shadowing" problems, where a smart pointer type can hide
methods in the pointee.
* Diagnostics and cleanup.
Naming: in this commit, the "Autoderef" type is modified so that it no
longer solely focuses on the "Deref" trait, but can now consider the
"Receiver" trait instead. Should it be renamed, to something like
"TraitFollower"? This was considered, but rejected, because
* even in the Receiver case, it still considers built-in derefs
* the name Autoderef is short and snappy.
Rename `projection_def_id` to `item_def_id`
Renames `projection_def_id` to `item_def_id`, since `item_def_id` is what we call the analogous method for ~~`AliasTerm`/`AliasTy`~~ `PolyExistentialProjection`. I keep forgetting that this one is not called `item_def_id`.
Validate self in host predicates correctly
`assert_only_contains_predicates_from` was added to make sure that we are computing predicates for the correct self type for a given `PredicateFilter`. That was not implemented correctly for `PredicateFilter::SelfOnly` when there are const predicates.
Fixes#133526
Make `Copy` unsafe to implement for ADTs with `unsafe` fields
As a rule, the application of `unsafe` to a declaration requires that use-sites of that declaration also entail `unsafe`. For example, a field declared `unsafe` may only be read in the lexical context of an `unsafe` block.
For nearly all safe traits, the safety obligations of fields are explicitly discharged when they are mentioned in method definitions. For example, idiomatically implementing `Clone` (a safe trait) for a type with unsafe fields will require `unsafe` to clone those fields.
Prior to this commit, `Copy` violated this rule. The trait is marked safe, and although it has no explicit methods, its implementation permits reads of `Self`.
This commit resolves this by making `Copy` conditionally safe to implement. It remains safe to implement for ADTs without unsafe fields, but unsafe to implement for ADTs with unsafe fields.
Tracking: #132922
r? ```@compiler-errors```
Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681.
Support default fields in enum struct variant
Allow default values in an enum struct variant definition:
```rust
pub enum Bar {
Foo {
bar: S = S,
baz: i32 = 42 + 3,
}
}
```
Allow using `..` without a base on an enum struct variant
```rust
Bar::Foo { .. }
```
`#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants.
Support `#[derive(Default)]` on enum struct variants with all defaulted fields
```rust
pub enum Bar {
#[default]
Foo {
bar: S = S,
baz: i32 = 42 + 3,
}
}
```
Check for missing fields in typeck instead of mir_build.
Expand test with `const` param case (needs `generic_const_exprs` enabled).
Properly instantiate MIR const
The following works:
```rust
struct S<A> {
a: Vec<A> = Vec::new(),
}
S::<i32> { .. }
```
Add lint for default fields that will always fail const-eval
We *allow* this to happen for API writers that might want to rely on users'
getting a compile error when using the default field, different to the error
that they would get when the field isn't default. We could change this to
*always* error instead of being a lint, if we wanted.
This will *not* catch errors for partially evaluated consts, like when the
expression relies on a const parameter.
Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`:
- Suggest adding a base expression if there are missing fields.
- Suggest enabling the feature if all the missing fields have optional values.
- Suggest removing `..` if there are no missing fields.
As a rule, the application of `unsafe` to a declaration requires that use-sites
of that declaration also require `unsafe`. For example, a field declared
`unsafe` may only be read in the lexical context of an `unsafe` block.
For nearly all safe traits, the safety obligations of fields are explicitly
discharged when they are mentioned in method definitions. For example,
idiomatically implementing `Clone` (a safe trait) for a type with unsafe fields
will require `unsafe` to clone those fields.
Prior to this commit, `Copy` violated this rule. The trait is marked safe, and
although it has no explicit methods, its implementation permits reads of `Self`.
This commit resolves this by making `Copy` conditionally safe to implement. It
remains safe to implement for ADTs without unsafe fields, but unsafe to
implement for ADTs with unsafe fields.
Tracking: #132922
Avoid `opaque type not constrained` errors in the presence of other errors
pulled out of https://github.com/rust-lang/rust/pull/128440
These errors carry no new information if the opaque type was actually used in a constraining (but erroneous) way somewhere.
Don't try and handle unfed `type_of` on anon consts
The `type_of` query for anon consts in the type system is actually implemented by feeding the return value during hir ty lowering, not the hir-based logic in `const_arg_anon_type_of`. The HIR based logic is incomplete (doesn't handle all hir nodes) and also generally wrong to call (re-lowers HIR or invokes typeck which can result in query cycles).
r? `@compiler-errors`
Approved in [ACP 491](https://github.com/rust-lang/libs-team/issues/491).
Remove the `unsafe` on `core::intrinsics::breakpoint()`, since it's a
safe intrinsic to call and has no prerequisites.
(Thanks to @zachs18 for figuring out the `bootstrap`/`not(bootstrap)`
logic.)
Deeply normalize when computing implied outlives bounds
r? lcnr
Unfortunately resolving regions is still slightly scuffed (though in an unrelated way). Specifically, we should be normalizing our param-env outlives when constructing the `OutlivesEnv`; otherwise, these assumptions (dd2837ec5d/compiler/rustc_infer/src/infer/outlives/env.rs (L78)) are not constructed correctly.
Let me know if you want us to track that somewhere.
Move `Const::{from_anon_const,try_from_lit}` to hir_ty_lowering
Fixes#128176.
This accomplishes one of the followup items from #131081.
These operations are much more about lowering the HIR than about
`Const`s themselves. They fit better in hir_ty_lowering with
`lower_const_arg` (formerly `Const::from_const_arg`) and the rest.
To accomplish this, `const_evaluatable_predicates_of` had to be changed
to not use `from_anon_const` anymore. Instead of visiting the HIR and
lowering anon consts on the fly, it now visits the `rustc_middle::ty`
data structures instead and directly looks for `UnevaluatedConst`s. This
approach was proposed in:
https://github.com/rust-lang/rust/pull/131081#discussion_r1821189257
r? `@BoxyUwU`
These operations are much more about lowering the HIR than about
`Const`s themselves. They fit better in hir_ty_lowering with
`lower_const_arg` (formerly `Const::from_const_arg`) and the rest.
To accomplish this, `const_evaluatable_predicates_of` had to be changed
to not use `from_anon_const` anymore. Instead of visiting the HIR and
lowering anon consts on the fly, it now visits the `rustc_middle::ty`
data structures instead and directly looks for `UnevaluatedConst`s. This
approach was proposed in:
https://github.com/rust-lang/rust/pull/131081#discussion_r1821189257
remove `Ty::is_copy_modulo_regions`
Using these functions is likely incorrect if an `InferCtxt` is available, I moved this function to `TyCtxt` (and added it to `LateContext`) and added a note to the documentation that one should prefer `Infer::type_is_copy_modulo_regions` instead.
I didn't yet move `is_sized` and `is_freeze`, though I think we should move these as well.
r? `@compiler-errors` cc #132279
Remove `hir::ArrayLen`
This refactoring removes `hir::ArrayLen`, replacing it with `hir::ConstArg`. To represent inferred array lengths (previously `hir::ArrayLen::Infer`), a new variant `ConstArgKind::Infer` is added.
r? `@BoxyUwU`
Robustify and genericize return-type-notation resolution in `resolve_bound_vars`
#129629 implemented return-type-notation (RTN) in its path form, like `where T::method(..): Bound`. As part of lowering, we must record the late-bound vars for the where clause introduced by the method (namely, its early- and late-bound lifetime arguments, since `where T::method(..)` turns into a higher-ranked where clause over all of the lifetimes according to [RFC 3654](https://rust-lang.github.io/rfcs/3654-return-type-notation.html#converting-to-higher-ranked-trait-bounds)).
However, this logic was only looking at the where clauses of the parent item that the `T::method(..)` bound was written on, and not any parent items. This PR generalizes that logic to look at the parent item (i.e. the outer impl or trait) instead and fixes a (debug only) assertion as an effect.
This logic is also more general and likely easier to adapt to more interesting (though likely very far off) cases like non-lifetime binder `for<T: Trait> T::method(..): Send` bounds.
Tracking:
- https://github.com/rust-lang/rust/issues/109417
Make `compare_impl_item` into a query
Turns `compare_impl_item` into a query (generalizing the existing query for `compare_impl_const`), and uses that in `Instance::resolve` to fail resolution when an implementation is incompatible with the trait it comes from.
Fixes#119701Fixes#121127Fixes#121411Fixes#129075Fixes#129127Fixes#129214Fixes#131294
Stabilize `extended_varargs_abi_support`
I think that is everything? If there is any documentation regarding `extern` and/or varargs to correct, let me know, some quick greps suggest that there might be none.
Tracking issue: https://github.com/rust-lang/rust/issues/100189
Actually use placeholder regions for trait method late bound regions in `collect_return_position_impl_trait_in_trait_tys`
So in https://github.com/rust-lang/rust/pull/113182, I introduced a "diagnostics improvement" in the form of 473c88dfb6, which changes which signature we end up instantiating with placeholder regions and which signature we end up instantiating with fresh region vars so that we have placeholders corresponding to the names of the late-bound regions coming from the *impl*.
However, this is not sound, since now we're essentially no longer proving that *all* instantiations of the trait method are compatible with an instantiation of the impl method, but vice versa (which is weaker). Let's look at the example `tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs`:
```rust
trait MkStatic {
fn mk_static(self) -> &'static str;
}
impl MkStatic for &'static str {
fn mk_static(self) -> &'static str { self }
}
trait Foo {
fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic;
}
impl Foo for str {
fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
self
}
}
fn call_foo<T: Foo + ?Sized>(t: &T) -> &'static str {
t.foo().mk_static()
}
fn main() {
let s = call_foo(String::from("hello, world").as_str());
println!("> {s}");
}
```
To collect RPITITs, we were previously instantiating the trait signature with infer vars (`fn(&'?0 str) -> ?1t` where `?1t` is the variable we use to infer the RPITIT) and the impl signature with placeholders (there are no late-bound regions in that signature, so we just have `fn(&'a str) -> Opaque`).
Equating the signatures works, since all we do is unify `?1t` with `Opaque` and `'?0` with `'a`. However, conceptually it *shouldn't* hold, since this definition is not valid for *all* instantiations of the trait method but just the one where `'0` (i.e. `'late`) is equal to `'a` :(
## So what
This PR effectively reverts 473c88dfb6 to fix the unsoundness.
Fixes#133427
Also fixes#133425, which is actually coincidentally another instance of this bug (but not one that is weaponized into UB, just one that causes an ICE in refinement checking).
Some minor dyn-related tweaks
Each commit should be self-explanatory, but I'm happy to explain what's going on if not. These are tweaks I pulled out of #133388, but they can be reviewed sooner than that.
r? types
Bail on more errors in dyn ty lowering
If we have more than one principal trait, or if we have a principal trait with errors in it, then bail with `TyKind::Error` rather than attempting lowering. Lowering a dyn trait with more than one principal just arbitrarily chooses the first one and drops the subsequent ones, and lowering a dyn trait path with errors in it is just kinda useless.
This suppresses unnecessary errors which I think is net-good, but also is important to make sure that we don't end up leaking `{type error}` in https://github.com/rust-lang/rust/issues/133388 error messaging :)
r? types
Refactor `where` predicates, and reserve for attributes support
Refactor `WherePredicate` to `WherePredicateKind`, and reserve for attributes support in `where` predicates.
This is a part of #115590 and is split from #132388.
r? petrochenkov
Support input/output in vector registers of s390x inline assembly (under asm_experimental_reg feature)
This extends currently clobber-only vector registers (`vreg`) support to allow passing `#[repr(simd)]` types, floats (f32/f64/f128), and integers (i32/i64/i128) as input/output.
This is unstable and gated under new `#![feature(asm_experimental_reg)]` (tracking issue: https://github.com/rust-lang/rust/issues/133416). If the feature is not enabled, only clober is supported as before.
| Architecture | Register class | Target feature | Allowed types |
| ------------ | -------------- | -------------- | -------------- |
| s390x | `vreg` | `vector` | `i32`, `f32`, `i64`, `f64`, `i128`, `f128`, `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
This matches the list of types that are supported by the vector registers in LLVM:
https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L301-L313
In addition to `core::simd` types and floats listed above, custom `#[repr(simd)]` types of the same size and type are also allowed. All allowed types other than i32/f32/i64/f64/i128, and relevant target features are currently unstable.
Currently there is no SIMD type for s390x in `core::arch`, but this is tracked in https://github.com/rust-lang/rust/issues/130869.
cc https://github.com/rust-lang/rust/issues/130869 about vector facility support in s390x
cc https://github.com/rust-lang/rust/issues/125398 & https://github.com/rust-lang/rust/issues/116909 about f128 support in asm
`@rustbot` label +O-SystemZ +A-inline-assembly
Store resolution for self and crate root module segments
Let's make sure to record the segment resolution for `self::`, `crate::` and `$crate::`.
I'm actually somewhat surprised that the only diagnostic that uses this is the one that errors on invalid generics on a module segment... but seems strictly more correct regardless, and there may be other diagnostics using these segments resolutions that just haven't been tested for `self`. Also includes a drive-by on `report_prohibit_generics_error`.
Rollup of 6 pull requests
Successful merges:
- #129838 (uefi: process: Add args support)
- #130800 (Mark `get_mut` and `set_position` in `std::io::Cursor` as const.)
- #132708 (Point at `const` definition when used instead of a binding in a `let` statement)
- #133226 (Make `PointerLike` opt-in instead of built-in)
- #133244 (Account for `wasm32v1-none` when exporting TLS symbols)
- #133257 (Add `UnordMap::clear` method)
r? `@ghost`
`@rustbot` modify labels: rollup
take 2
open up coroutines
tweak the wordings
the lint works up until 2021
We were missing one case, for ADTs, which was
causing `Result` to yield incorrect results.
only include field spans with significant types
deduplicate and eliminate field spans
switch to emit spans to impl Drops
Co-authored-by: Niko Matsakis <nikomat@amazon.com>
collect drops instead of taking liveness diff
apply some suggestions and add explantory notes
small fix on the cache
let the query recurse through coroutine
new suggestion format with extracted variable name
fine-tune the drop span and messages
bugfix on runtime borrows
tweak message wording
filter out ecosystem types earlier
apply suggestions
clippy
check lint level at session level
further restrict applicability of the lint
translate bid into nop for stable mir
detect cycle in type structure
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`.
Check `use<..>` in RPITIT for refinement
`#![feature(precise_capturing_in_traits)]` allows users to write `+ use<>` bounds on RPITITs to control what lifetimes are captured by the RPITIT.
Since RPITITs currently also warn for refinement in implementations, this PR extends that refinement check for cases where we *undercapture* in an implementation, since that may be indirectly "promising" a more relaxed outlives bound than the impl author intended.
For an opaque to be refining, we need to capture *fewer* parameters than those mentioned in the captured params of the trait. For example:
```
trait TypeParam<T> {
fn test() -> impl Sized;
}
// Indirectly capturing a lifetime param through a type param substitution.
impl<'a> TypeParam<&'a ()> for i32 {
fn test() -> impl Sized + use<> {}
//~^ WARN impl trait in impl method captures fewer lifetimes than in trait
}
```
Since the opaque in the method (implicitly) captures `use<Self, T>`, and `Self = i32, T = &'a ()` in the impl, we must mention `'a` in our `use<..>` on the impl.
Tracking:
* https://github.com/rust-lang/rust/issues/130044