Parse `impl` restrictions
This PR implements the parsing logic for `impl` restrictions (e.g., `pub impl(crate) trait Foo {}`) as proposed in [RFC 3323](https://rust-lang.github.io/rfcs/3323-restrictions.html).
As the first step of the RFC implementation, this PR focuses strictly on the parsing phase. The new syntax is guarded by the `#![feature(impl_restriction)]` feature gate.
This implementation basically follows the pattern used in rust-lang/rust#141754.
r? @jhpratt
core: make atomic primitives type aliases of `Atomic<T>`
Tracking issue: https://github.com/rust-lang/rust/issues/130539
This makes `AtomicI32` and friends type aliases of `Atomic<T>` by encoding their alignment requirements via the use of an internal `Storage` associated type. This is also used to encode that `AtomicBool` store a `u8` internally.
Modulo the `Send`/`Sync` implementations, this PR does not move any trait implementations, methods or associated functions – I'll leave that for another PR.
add field representing types
*[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/152730)*
> [!NOTE]
> This is a rewrite of #146307 by using a lang item instead of a custom `TyKind`. We still need a `hir::TyKind::FieldOf` variant, because resolving the field name cannot be done before HIR construction. The advantage of doing it this way is that we don't need to make any changes to types after HIR (including symbol mangling). At the very beginning of this feature implementation, I tried to do it using a lang item, but then quickly abandoned the approach, because at that time I was still intending to support nested fields.
Here is a [range-diff](https://triagebot.infra.rust-lang.org/gh-range-diff/rust-lang/rust/605f49b27444a738ea4032cb77e3bdc4eb811bab..d15f5052095b3549111854a2555dd7026b0a729e/605f49b27444a738ea4032cb77e3bdc4eb811bab..f5f42d1e03495dbaa23671c46b15fccddeb3492f) between the two PRs
---
# Add Field Representing Types (FRTs)
This PR implements the first step of the field projection lang experiment (Tracking Issue: rust-lang/rust#145383). Field representing types (FRTs) are a new kind of type. They can be named through the use of the `field_of!` macro with the first argument being the type and the second the name of the field (or variant and field in the case of an enum). No nested fields are supported.
FRTs natively implement the `Field` trait that's also added in this PR. It exposes information about the field such as the type of the field, the type of the base (i.e. the type that contains the field) and the offset within that base type. Only fields of non-packed structs are supported, fields of enums an unions have unique types for each field, but those do not implement the `Field` trait.
This PR was created in collaboration with @dingxiangfei2009, it wouldn't have been possible without him, so huge thanks for mentoring me!
I updated my library solution for field projections to use the FRTs from `core` instead of creating my own using the hash of the name of the field. See the [Rust-for-Linux/field-projection `lang-experiment` branch](https://github.com/Rust-for-Linux/field-projection/tree/lang-experiment).
## API added to `core::field`
```rust
pub unsafe trait Field {
type Base;
type Type;
const OFFSET: usize;
}
pub macro field_of($Container:ty, $($fields:expr)+ $(,)?);
```
Along with a perma-unstable type that the compiler uses in the expansion of the macro:
```rust
#[unstable(feature = "field_representing_type_raw", issue = "none")]
pub struct FieldRepresentingType<T: ?Sized, const VARIANT: u32, const FIELD: u32> {
_phantom: PhantomData<T>,
}
```
## Explanation of Field Representing Types (FRTs)
FRTs are used for compile-time & trait-level reflection for fields of structs & tuples. Each struct & tuple has a unique compiler-generated type nameable through the `field_of!` macro. This type natively contains information about the field such as the outermost container, type of the field and its offset. Users may implement additional traits on these types in order to record custom information (for example a crate may define a [`PinnableField` trait](https://github.com/Rust-for-Linux/field-projection/blob/lang-experiment/src/marker.rs#L9-L23) that records whether the field is structurally pinned).
They are the foundation of field projections, a general operation that's generic over the fields of a struct. This genericism needs to be expressible in the trait system. FRTs make this possible, since an operation generic over fields can just be a function with a generic parameter `F: Field`.
> [!NOTE]
> The approach of field projections has changed considerably since this PR was opened. In the end we might not need FRTs, so this API is highly experimental.
FRTs should act as though they were defined as `struct MyStruct_my_field<StructGenerics>;` next to the struct. So it should be local to the crate defining the struct so that one can implement any trait for the FRT from that crate. The `Field` traits should be implemented by the compiler & populated with correct information (`unsafe` code needs to be able to rely on them being correct).
## TODOs
There are some `FIXME(FRTs)` scattered around the code:
- Diagnostics for `field_of!` can be improved
- `tests/ui/field_representing_types/nonexistent.rs`
- `tests/ui/field_representing_types/non-struct.rs`
- `tests/ui/field_representing_types/offset.rs`
- `tests/ui/field_representing_types/not-field-if-packed.rs`
- `tests/ui/field_representing_types/invalid.rs`
- Simple type alias already seem to work, but might need some extra work in `compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs`
r? @oli-obk
Use `HashStable` derive in more places
This applies `HashStable` derive in a couple more places. Also `stable_hasher` is declared for `HashStable_NoContext`.
rustc_expand: improve diagnostics for non-repeatable metavars in repetition
Enhance `NoSyntaxVarsExprRepeat` by suggesting similarly named metavariables, distinguishing repeatable vs non-repeatable bindings, and listing available repeatable variables when no match exists.
Reflection TypeKind::FnPtr
This is for https://github.com/rust-lang/rust/issues/146922.
Const-eval currently lacks full support for function pointer (fn) types. We should implement handling of FnPtr TypeKind, covering safe and unsafe functions, Rust and custom ABIs, input and output types, higher-ranked lifetimes, and variadic functions.
- Implement handling of FnPtr TypeKind in const-eval, including:
- Unsafety flag (safe vs unsafe fn)
- ABI variants (Rust, Named(C), Named(custom))
- Input and output types
- Variadic function pointers
- Add const-eval tests covering:
- Basic Rust fn() pointers
- Unsafe fn() pointers
- Extern C and custom ABI pointers
- Functions with multiple inputs and output types
- Variadic functions
- Use const TypeId checks to verify correctness of inputs, outputs, and payloads
Enhance `NoSyntaxVarsExprRepeat` by suggesting similarly named
metavariables, distinguishing repeatable vs non-repeatable bindings,
and listing available repeatable variables when no match exists.
Co-authored-by: Esteban Küber <esteban@kuber.com.ar>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Implement RFC 3678: Final trait methods
Tracking: https://github.com/rust-lang/rust/issues/131179
This PR is based on rust-lang/rust#130802, with some minor changes and conflict resolution.
Futhermore, this PR excludes final methods from the vtable of a dyn Trait.
And some excerpt from the original PR description:
> Implements the surface part of https://github.com/rust-lang/rfcs/pull/3678.
>
> I'm using the word "method" in the title, but in the diagnostics and the feature gate I used "associated function", since that's more accurate.
cc @joshtriplett
replace box_new with lower-level intrinsics
The `box_new` intrinsic is super special: during THIR construction it turns into an `ExprKind::Box` (formerly known as the `box` keyword), which then during MIR building turns into a special instruction sequence that invokes the exchange_malloc lang item (which has a name from a different time) and a special MIR statement to represent a shallowly-initialized `Box` (which raises [interesting opsem questions](https://github.com/rust-lang/rust/issues/97270)).
This PR is the n-th attempt to get rid of `box_new`. That's non-trivial because it usually causes a perf regression: replacing `box_new` by naive unsafe code will incur extra copies in debug builds, making the resulting binaries a lot slower, and will generate a lot more MIR, making compilation measurably slower. Furthermore, `vec!` is a macro, so the exact code it expands to is highly relevant for borrow checking, type inference, and temporary scopes.
To avoid those problems, this PR does its best to make the MIR almost exactly the same as what it was before. `box_new` is used in two places, `Box::new` and `vec!`:
- For `Box::new` that is fairly easy: the `move_by_value` intrinsic is basically all we need. However, to avoid the extra copy that would usually be generated for the argument of a function call, we need to special-case this intrinsic during MIR building. That's what the first commit does.
- `vec!` is a lot more tricky. As a macro, its details leak to stable code, so almost every variant I tried broke either type inference or the lifetimes of temporaries in some ui test or ended up accepting unsound code due to the borrow checker not enforcing all the constraints I hoped it would enforce. I ended up with a variant that involves a new intrinsic, `fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, x: T) -> Box<MaybeUninit<T>>`, that writes a value into a `Box<MaybeUninit<T>>` and returns that box again. In exchange we can get rid of somewhat similar code in the lowering for `ExprKind::Box`, and the `exchange_malloc` lang item. (We can also get rid of `Rvalue::ShallowInitBox`; I didn't include that in this PR -- I think @cjgillot has a commit for this somewhere [around here](https://github.com/rust-lang/rust/pull/147862/commits).)
See [here](https://github.com/rust-lang/rust/pull/148190#issuecomment-3457454814) for the latest perf numbers. Most of the regressions are in deep-vector which consists entirely of an invocation of `vec!`, so any change to that macro affects this benchmark disproportionally.
This is my first time even looking at MIR building code, so I am very low confidence in that part of the patch, in particular when it comes to scopes and drops and things like that.
I also had do nerf some clippy tests because clippy gets confused by the new expansion of `vec!` so it makes fewer suggestions when `vec!` is involved.
### `vec!` FAQ
- Why does `write_box_via_move` return the `Box` again? Because we need to expand `vec!` to a bunch of method invocations without any blocks or let-statements, or else the temporary scopes (and type inference) don't work out.
- Why is `box_assume_init_into_vec_unsafe` (unsoundly!) a safe function? Because we can't use an unsafe block in `vec!` as that would necessarily also include the `$x` (due to it all being one big method invocation) and therefore interpret the user's code as being inside `unsafe`, which would be bad (and 10 years later, we still don't have safe blocks for macros like this).
- Why does `write_box_via_move` use `Box` as input/output type, and not, say, raw pointers? Because that is the only way to get the correct behavior when `$x` panics or has control effects: we need the `Box` to be dropped in that case. (As a nice side-effect this also makes the intrinsic safe, which is imported as explained in the previous bullet.)
- Can't we make it safe by having `write_box_via_move` return `Box<T>`? Yes we could, but there's no easy way for the intrinsic to convert its `Box<MaybeUninit<T>>` to a `Box<T>`. Transmuting would be unsound as the borrow checker would no longer properly enforce that lifetimes involved in a `vec!` invocation behave correctly.
- Is this macro truly cursed? Yes, yes it is.
support c-variadic functions in `rustc_const_eval`
tracking issue: https://github.com/rust-lang/rust/issues/44930
The new `GlobalAlloc::VaList` is used to create an `AllocId` that represents the variable argument list of a frame. The allocation itself does not store any data, all we need is the unique identifier.
The actual variable argument list is stored in `Memory`, and keyed by the `AllocId`. The `Frame` also stores this `AllocId`, so that when a frame is popped, it can deallocate the variable arguments.
At "runtime" a `VaList` value stores a pointer to the global allocation in its first bytes. The provenance on this pointer can be used to retrieve its `AllocId`, and the offset of the pointer is used to store the index of the next argument to read from the variable argument list.
Miri does not yet support `va_arg`, but I think that can be done separetely?
r? @RalfJung
cc @workingjubilee
Pass alignments through the shim as `Alignment` (not `usize`)
We're using `Layout` on both sides, so might as well skip the transmutes back and forth to `usize`.
The mir-opt test shows that doing so allows simplifying the boxed-slice drop slightly, for example.
We're using `Layout` on both sides, so might as well skip the transmutes back and forth to `usize`.
The mir-opt test shows that doing so allows simplifying the boxed-slice drop slightly, for example.
Support ADT types in type info reflection
Tracking issue: rust-lang/rust#146922 `#![feature(type_info)]`
This PR supports ADT types for feature `type_info` reflection.
(It's still a draft PR, with implementation in progress)
Note that this PR does not take SemVer into consideration (I left a FIXME comment). As discussed earlier ([comment](https://github.com/rust-lang/rust/pull/146923#discussion_r2372249477)), this requires further discussion. However, I hope we could get an initial implementation to land first, so we can start playing with it.
### Progress / Checklist
- [x] Struct support.
- [x] Enum
- [x] Union
- [x] Generics
- [ ] ~Methods~ Implemented and to be implemented in other PRs
- [ ] ~Traits~ Implemented and to be implemented in other PRs
- [x] Rebasing PR to `main` branch
~~(It's currently based on PR rust-lang/rust#151123, so here's an extra commit)~~
- [x] Cleanup and Rebase.
- [x] Fix field info for references. (see [comment](https://github.com/rust-lang/rust/pull/151142#discussion_r2777920512))
r? @oli-obk
Remove `SubdiagMessage` in favour of the identical `DiagMessage`
For https://github.com/rust-lang/rust/issues/151366
Just some more cleanup :)
SubdiagMessage is now identical to DiagMessage, so there's no point in having both of them
Revert, but without type const.
Update symbol for feature err, then update suggestion output, and lastly update tests that change because of those.
Update these new tests with the correct syntax, and few existing tests with the new outputs the merge with main added.
Fix for tidyfmt and some errors when manually resolving a merge conflicts.
Update these tests to use update error messages and type const syntax.
Update comments and error message to use new syntax instead of old type_const attribute.
Remove the type_const attribute
update some more tests to use the new syntax.
Update these test cases.
update feature gate test
Change gate logic for `mgca_type_const_syntax` to work also if `min_generic_const_args` is enabled.
Create a new feature gate that checks for the feature before expansion.
Make rustfmt handle the `type const` syntax correctly.
Add a convience method to check if a RhsKind is type const.
Rename `Const` discriminant to `Body` for `ConstItemRhsKind`
Give the `TraitItemKind` flag an enum instead of a simple bool to better describe what the flag is for.
Update formatting for these match statements.
Update clippy test to use type const syntax.
Update test to use type const syntax.
update rustfmt to match ast items.
Update clippy to match ast and hir items.
Few more test cases that used old attribute, instead of 'type const'
Update to match the output from the feature gate checks.
tidyfmt adjustments.
Update the is_type_const, so I can constrain record!(..) in encoder.rs
Update conditional compilation test.
Move the feature gate to after expansion to allow for cfg(...) to work.
Update some more tests to use the new syntax.
Update type const tests in associated-const-bindings to use new syntax.
Don't check based off the attribute, but the item here.
Update some tests outside of the const_generics folder that were using #[type_const]
update the tests in associated consts that use #[type_const] to use type const
Update these mgca tests with the type const syntax.
Add a flag to TraitItemKind for detecting type const for now. Maybe later change ItemConstRhs to have optional consts but that touches a lot more lines of code.
Don't need into for these now that it's a query.
Add is_type_const query to handle foreign def ids.
update this test to use type const syntax.
Fix logic here, we only want to lower if there is expression in this case.
Update built-in macros to use ConstItemRhsKind
Update more instance of the old ConstItemRhs.
Rename ConstItemKind to ConstItemRhsKind, I noticed there is a typed called ConstantItemKind, so add the Rhs to the name to avoid confusion.
Update lower to use ConstItemKind
Add an other helper method to check if the rhs kinda has an expr.
Update item parse to use ConstItemKind enum.
Felt the field name could a be little clear when editing a few other things.
Change the ConstItem struct see know if we have a type const or regular const.
Make sure this syntax is properly feature gated.
Implement MVP for opaque generic const arguments
This is meant to be the interim successor to generic const expressions.
Essentially, const item RHS's will be allowed to do arbitrary const
operations using generics. The limitation is that these const items will
be treated opaquely, like ADTs in nominal typing, such that uses of them
will only be equal if the same const item is referenced. In other words,
two const items with the exact same RHS will not be considered equal.
I also added some logic to check feature gates that depend on others
being enabled (like oGCA depending on mGCA).
### Coherence
During coherence, OGCA consts should be normalized ambiguously because
they are opaque but eventually resolved to a real value. We don't want
two OGCAs that have the same value to be treated as distinct for
coherence purposes. (Just like opaque types.)
This actually doesn't work yet because there are pre-existing
fundamental issues with equate relations involving consts that need to
be normalized. The problem is that we normalize only one layer of the
const item and don't actually process the resulting anon const. Normally
the created inference variable should be handled, which in this case
would cause us to hit the anon const, but that's not happening.
Specifically, `visit_const` on `Generalizer` should be updated to be
similar to `visit_ty`.
r? @BoxyUwU
Streamline `rustc_span::HashStableContext`.
Currently this trait has five methods. But it only really needs three.
For example, currently stable hashing of spans is implemented in `rustc_span`, except a couple of sub-operations are delegated to `rustc_query_system`: `def_span` and `span_data_to_lines_and_cols`. These two delegated sub-operations can be reduced to a single delegated operation that does the full hash computation.
Likewise, `assert_default_hashing_controls` depends on two delegated sub-operations, `hashing_controls` and
`unstable_opts_incremental_ignore_spans`, and can be simplified.
I find the resulting code simpler and clearer -- when necessary, we do a whole operation in `rustc_query_system` instead of doing it partly in `rustc_span` and partly in `rustc_query_system`.
r? @cjgillot
Fix `SourceFile::normalized_byte_pos`
This method was broken by 258ace6, which changed `self.normalized_pos` to use relative offsets however this method continued to compare against an absolute offset.
Also adds a regression test for the issue that this method was originally introduced to fix.
Closesrust-lang/rust#149568
Fixes regression of rust-lang/rust#110885
r? cjgillot (as author of the breaking commit)
This is meant to be the interim successor to generic const expressions.
Essentially, const item RHS's will be allowed to do arbitrary const
operations using generics. The limitation is that these const items will
be treated opaquely, like ADTs in nominal typing, such that uses of them
will only be equal if the same const item is referenced. In other words,
two const items with the exact same RHS will not be considered equal.
I also added some logic to check feature gates that depend on others
being enabled (like oGCA depending on mGCA).
= Coherence =
During coherence, OGCA consts should be normalized ambiguously because
they are opaque but eventually resolved to a real value. We don't want
two OGCAs that have the same value to be treated as distinct for
coherence purposes. (Just like opaque types.)
This actually doesn't work yet because there are pre-existing
fundamental issues with equate relations involving consts that need to
be normalized. The problem is that we normalize only one layer of the
const item and don't actually process the resulting anon const. Normally
the created inference variable should be handled, which in this case
would cause us to hit the anon const, but that's not happening.
Specifically, `visit_const` on `Generalizer` should be updated to be
similar to `visit_ty`.