-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
Add field representing types #146307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add field representing types #146307
Conversation
2bd0ff4 to
a6b191a
Compare
|
changes to the core type system Some changes occurred in src/tools/clippy cc @rust-lang/clippy Some changes occurred in diagnostic error codes Some changes occurred to the CTFE machinery Some changes occurred in compiler/rustc_sanitizers cc @rcvalle HIR ty lowering was modified cc @fmease Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred to the CTFE / Miri interpreter cc @rust-lang/miri Some changes occurred in exhaustiveness checking cc @Nadrieril This PR changes MIR cc @oli-obk, @RalfJung, @JakobDegen, @vakaras Some changes occurred in compiler/rustc_codegen_ssa This PR changes rustc_public cc @oli-obk, @celinval, @ouz-a Some changes occurred in src/tools/rustfmt cc @rust-lang/rustfmt Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some changes to symbol mangling & constant names that I'm not sure how they resulted from my changes. Anybody has any idea?
|
Some changes occurred to constck cc @fee1-dead |
This comment has been minimized.
This comment has been minimized.
|
Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you ensure you have a test that is generic over the field and that queries the offset? That would hit all these points I just mentioned here (or at least some of them), and anyway seems like a very non-trivial case to test.
Or... wait the intrinsic is only used to define that one associated const? I don't know exactly when and how we normalize those but it may be that we indeed never see that MIR in its generic form then...
The test may have to invoke the intrinsic directly to trigger the case I am thinking of.
…mpatible_trait]`
86ed982 to
d9dab43
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Add Field Representing Types (FRTs)
This PR implements the first step of the field projection lang experiment (Tracking Issue: #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
Fieldtrait 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 theFieldtrait.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
coreinstead of creating my own using the hash of the name of the field. See the Rust-for-Linux/field-projectionlang-experimentbranch.API added to
core::fieldExplanation 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 aPinnableFieldtrait 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. TheFieldtraits should be implemented by the compiler & populated with correct information (unsafecode needs to be able to rely on them being correct).Design Decisions
During the development several desirable properties of FRTs were discovered. Either due to simplifying the implementation or because of language design reasons. These decisions are:
FRTs are inhabited ZSTs, they have the same layout as
()Fieldtrait. Their only use of the values is a future ergonomics change that allows skipping turbofish syntax.FreezeThe coherence check of FRTs amounts to checking coherence of the base type.
So
field_of!(Foo, bar)is local ifFoois local (Baris allowed to be foreign). Fundamental types are not handled specially, sofield_of!(MaybeUninit<Struct>, value)still is local tocore(aside from the fact that non-visible fields cannot be accessed in the first place).Traits may be implemented for FRTs in the usual way (so if the FRT or the trait is local). There is an exception:
Drop: since FRTs are uninhabited, having aDropimpl doesn't really make sense. It also would have required duplicating a lot of logic from ADTs and as such it simplified the implementation.The
Fieldtrait is not user-implementableFRTs implement all auto traits as well as
CopyandClone.TODOs
There are several
FIXME(FRTs)scattered around the code:src/librustdoc/json/conversions.rscompiler/rustc_codegen_ssa/src/debuginfo/type_names.rscompiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rscompiler/rustc_symbol_mangling/src/v0.rsfield_of!can be improvedtests/ui/field_representing_types/nonexistent.rstests/ui/field_representing_types/non-struct.rstests/ui/field_representing_types/offset.rstests/ui/field_representing_types/not-field-if-packed.rstests/ui/field_representing_types/invalid.rscompiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs