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](605f49b274..f5f42d1e03) 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
Rename `rustc::pass_by_value` lint as `rustc::disallowed_pass_by_ref`.
The name `pass_by_value` is completely wrong. The lint actually checks for the use of pass by reference for types marked with `rustc_pass_by_value`.
The hardest part of this was choosing the new name. The `disallowed_` part of the name closely matches the following clippy lints:
- `disallowed_macros`
- `disallowed_methods`
- `disallowed_names`
- `disallowed_script_idents`
- `disallowed_types`
The `pass_by_value` part of the name aligns with the following clippy lints:
- `needless_pass_by_value`
- `needless_pass_by_ref_mut`
- `trivially_copy_pass_by_ref`
- `large_types_passed_by_value` (less so)
r? @Urgau
rustc_target: callconv: powerpc64: Use llvm_abiname rather than target_abi for ABI determination
Currently on PowerPC64 targets, `llvm_abiname` and `target_abi` will be the same unless we're on AIX. Since `llvm_abiname` is what we pass on to LLVM, it is preferable to use the value of that to determine the calling convention rather than `target_abi`.
All PowerPC64 targets set both `llvm_abiname` and `target_abi` to the respective ELF ABIs, with the exception of AIX. This is a non-functional change.
Noticed this in the follow-up discussion from rust-lang/rust#150468 and also requested by @RalfJung [here](https://github.com/rust-lang/rust/pull/150468#discussion_r2842291237).
r? @RalfJung
Fix: On wasm targets, call `panic_in_cleanup` if panic occurs in cleanup
Previously this was not correctly implemented. Each funclet may need its own terminate block, so this changes the `terminate_block` into a `terminate_blocks` `IndexVec` which can have a terminate_block for each funclet. We key on the first basic block of the funclet -- in particular, this is the start block for the old case of the top level terminate function.
I also fixed the `terminate` handler to not be invoked when a foreign exception is raised, mimicking the behavior from msvc. On wasm, in order to avoid generating a `catch_all` we need to call `llvm.wasm.get.exception` and `llvm.wasm.get.ehselector`.
Currently the rustfmt slow test fails if you don't have a nightly
toolchain installed. We install a nightly toolchain on CI, but it's a
little confusing that tests can fail on a fresh checkout on a new
laptop.
Instead, skip this test if there's no nightly toolchain.
the `check_ptr_ptr_cast` function had an early return when the source and
destination dyn trait objects shared the same principal trait def id:
if src_principal == dst_principal {
return Ok(());
}
this bypassed all three remaining checks that the code comment explicitly
listed as required: generic argument equality, projection equality, and
the auto-trait superset check. as a result, casts like
`*mut dyn Trait as *mut (dyn Trait + Send)` were silently accepted
instead of emitting E0804.
the fix removes the early return. `CastError::PtrPtrAddingAutoTraits` and
its diagnostic were already implemented — they just couldn't be reached.
the supertrait case (`trait Trait: Send`) continues to work correctly
because the auto-trait check already accounts for implied auto traits via
supertrait elaboration.
rustdoc: Improve sentence for documented empty impl blocks
Part of rust-lang/rust#152874.
An impl block is not necessarily empty, so instead, better to precise that there are no **public** items.
r? @Urgau
Superficial tweaks to the query modifier docs in `rustc_middle::query::modifiers`
This PR sorts the dummy items in the `modifiers` module, makes them non-pub to speed up find-all-references, and adds some extra explanation of what the dummy modifier items are for.
(These dummy items mostly just exist to carry documentation, and have no actual effect on compiler behaviour.)
fix interpreter tracing output
https://github.com/rust-lang/rust/pull/144708 accidentally changed the output of `MIRI_LOG=info <miri run>` in two ways:
- by adding `stmt=`/`terminator=` prefixes
- by changing the statement printing to be a verbose debug version instead of MIR pretty-printing
This fixes both of these:
- use explicit format strings to avoid the prefixes
- fix inconsistency in Debug impls for MIR types: now both TerminatorKind and StatementKind are pretty-printed, and Terminator and Statement just forward to the *Kind output
Revert relative paths for std links in rustc-docs
Reverts rust-lang/rust#152243.
The relative path `../` passed via `--extern-html-root-url` produces broken links in compiler documentation. The path is wrong in both the published layout (`doc.rust-lang.org/nightly/nightly-rustc/` vs `doc.rust-lang.org/nightly/core/`) and local builds (`compiler-doc/` vs `doc/`).
This restores absolute URLs via `#[doc(html_root_url)]`.
Fixesrust-lang/rust#152917
Re-opens rust-lang/rust#151496
cc @eggyal
Enable rust.remap-debuginfo in the dist profile
Anyone who distributes rustc almost certainly wants to enable this option. It is necessary for reproducibility and for a distributed rustc local paths are useless anyway. And finally it improves privacy if you distribute a local build.
Simplify ThinLTO handling
This reduces the amount of complexity around ThinLTO module buffers. It removes duplication between `ModuleBuffer` and `ThinBuffer` (the latter was also used for fat LTO in some cases), clarifies when and where the ThinLTO summary is used (only for `--emit thin-link-bitcode`, ThinLTO performed by rustc rebuilds the summary every time). This also enables a follow up cleanup to reduce code duplication between red, green and imported codegen units.
Part of https://github.com/rust-lang/compiler-team/issues/908