Skip to content

Commit 7b42859

Browse files
committed
add field representing types
1 parent b081bc8 commit 7b42859

86 files changed

Lines changed: 2105 additions & 32 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4748,6 +4748,7 @@ dependencies = [
47484748
"ena",
47494749
"indexmap",
47504750
"rustc-hash 2.1.1",
4751+
"rustc_abi",
47514752
"rustc_ast_ir",
47524753
"rustc_data_structures",
47534754
"rustc_error_messages",

compiler/rustc_ast/src/ast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,11 @@ pub enum TyKind {
25532553
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
25542554
/// just as part of the type system.
25552555
Pat(Box<Ty>, Box<TyPat>),
2556+
/// A `field_of` expression (e.g., `builtin # field_of(Struct, field)`).
2557+
///
2558+
/// Usually not written directly in user code but indirectly via the macro
2559+
/// `core::field::field_of!(...)`.
2560+
FieldOf(Box<Ty>, Option<Ident>, Ident),
25562561
/// Sometimes we need a dummy value when no error has occurred.
25572562
Dummy,
25582563
/// Placeholder for a kind that has failed to be defined.

compiler/rustc_ast/src/util/classify.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
298298
| ast::TyKind::ImplicitSelf
299299
| ast::TyKind::CVarArgs
300300
| ast::TyKind::Pat(..)
301+
| ast::TyKind::FieldOf(..)
301302
| ast::TyKind::Dummy
302303
| ast::TyKind::Err(..) => break None,
303304
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,6 +1496,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14961496
TyKind::Pat(ty, pat) => {
14971497
hir::TyKind::Pat(self.lower_ty_alloc(ty, itctx), self.lower_ty_pat(pat, ty.span))
14981498
}
1499+
TyKind::FieldOf(ty, variant, field) => hir::TyKind::FieldOf(
1500+
self.lower_ty_alloc(ty, itctx),
1501+
self.arena.alloc(hir::TyFieldPath {
1502+
variant: variant.map(|variant| self.lower_ident(variant)),
1503+
field: self.lower_ident(*field),
1504+
}),
1505+
),
14991506
TyKind::MacCall(_) => {
15001507
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
15011508
}

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,23 @@ impl<'a> State<'a> {
13771377
self.word(" is ");
13781378
self.print_ty_pat(pat);
13791379
}
1380+
ast::TyKind::FieldOf(ty, variant, field) => {
1381+
self.word("builtin # field_of");
1382+
self.popen();
1383+
let ib = self.ibox(0);
1384+
self.print_type(ty);
1385+
self.word(",");
1386+
self.space();
1387+
1388+
if let Some(variant) = variant {
1389+
self.print_ident(*variant);
1390+
self.word(".");
1391+
}
1392+
self.print_ident(*field);
1393+
1394+
self.end(ib);
1395+
self.pclose();
1396+
}
13801397
}
13811398
self.end(ib);
13821399
}

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use rustc_middle::mir::AssertMessage;
1212
use rustc_middle::mir::interpret::ReportedErrorInfo;
1313
use rustc_middle::query::TyCtxtAt;
1414
use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement};
15-
use rustc_middle::ty::{self, Ty, TyCtxt};
16-
use rustc_middle::{bug, mir};
15+
use rustc_middle::ty::{self, FieldInfo, Ty, TyCtxt};
16+
use rustc_middle::{bug, mir, span_bug};
1717
use rustc_span::{Span, Symbol, sym};
1818
use rustc_target::callconv::FnAbi;
1919
use tracing::debug;
@@ -23,8 +23,9 @@ use crate::errors::{LongRunning, LongRunningWarn};
2323
use crate::interpret::{
2424
self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
2525
GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar,
26-
compile_time_machine, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub,
27-
throw_ub_custom, throw_unsup, throw_unsup_format, type_implements_dyn_trait,
26+
compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust,
27+
throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format,
28+
type_implements_dyn_trait,
2829
};
2930

3031
/// When hitting this many interpreted terminators we emit a deny by default lint
@@ -619,6 +620,27 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
619620
ecx.write_type_info(ty, dest)?;
620621
}
621622

623+
sym::field_offset => {
624+
let frt_ty = instance.args.type_at(0);
625+
ensure_monomorphic_enough(ecx.tcx.tcx, frt_ty)?;
626+
627+
let (ty, variant, field) = if let ty::Adt(def, args) = frt_ty.kind()
628+
&& let Some(FieldInfo { base, variant_idx, field_idx, .. }) =
629+
def.field_representing_type_info(ecx.tcx.tcx, args)
630+
{
631+
(base, variant_idx, field_idx)
632+
} else {
633+
span_bug!(ecx.cur_span(), "expected field representing type, got {frt_ty}")
634+
};
635+
let layout = ecx.layout_of(ty)?;
636+
let cx = ty::layout::LayoutCx::new(ecx.tcx.tcx, ecx.typing_env());
637+
638+
let layout = layout.for_variant(&cx, variant);
639+
let offset = layout.fields.offset(field.index()).bytes();
640+
641+
ecx.write_scalar(Scalar::from_target_usize(offset, ecx), dest)?;
642+
}
643+
622644
_ => {
623645
// We haven't handled the intrinsic, let's see if we can use a fallback body.
624646
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {

compiler/rustc_const_eval/src/interpret/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ use self::place::{MemPlace, Place};
3838
pub use self::projection::{OffsetMode, Projectable};
3939
pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation};
4040
pub use self::util::EnteredTraceSpan;
41-
pub(crate) use self::util::{create_static_alloc, type_implements_dyn_trait};
41+
pub(crate) use self::util::{
42+
create_static_alloc, ensure_monomorphic_enough, type_implements_dyn_trait,
43+
};
4244
pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};
4345
pub use self::visitor::ValueVisitor;

compiler/rustc_feature/src/unstable.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ declare_features! (
221221
(internal, custom_mir, "1.65.0", None),
222222
/// Implementation details of externally implementable items
223223
(internal, eii_internals, "1.94.0", None),
224+
/// Implementation details of field representing types.
225+
(internal, field_representing_type_raw, "CURRENT_RUSTC_VERSION", None),
224226
/// Outputs useful `assert!` messages
225227
(unstable, generic_assert, "1.63.0", None),
226228
/// Allows using the #[rustc_intrinsic] attribute.
@@ -486,6 +488,8 @@ declare_features! (
486488
(unstable, ffi_const, "1.45.0", Some(58328)),
487489
/// Allows the use of `#[ffi_pure]` on foreign functions.
488490
(unstable, ffi_pure, "1.45.0", Some(58329)),
491+
/// Experimental field projections.
492+
(incomplete, field_projections, "CURRENT_RUSTC_VERSION", Some(145383)),
489493
/// Allows marking trait functions as `final` to prevent overriding impls
490494
(unstable, final_associated_functions, "CURRENT_RUSTC_VERSION", Some(131179)),
491495
/// Controlling the behavior of fmt::Debug

compiler/rustc_hir/src/hir.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,6 +1741,12 @@ impl<'hir> Block<'hir> {
17411741
}
17421742
}
17431743

1744+
#[derive(Debug, Clone, Copy, HashStable_Generic)]
1745+
pub struct TyFieldPath {
1746+
pub variant: Option<Ident>,
1747+
pub field: Ident,
1748+
}
1749+
17441750
#[derive(Debug, Clone, Copy, HashStable_Generic)]
17451751
pub struct TyPat<'hir> {
17461752
#[stable_hasher(ignore)]
@@ -3804,6 +3810,10 @@ pub enum TyKind<'hir, Unambig = ()> {
38043810
Err(rustc_span::ErrorGuaranteed),
38053811
/// Pattern types (`pattern_type!(u32 is 1..)`)
38063812
Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>),
3813+
/// Field representing type (`field_of!(Struct, field)`).
3814+
///
3815+
/// The optional ident is the variant when an enum is passed `field_of!(Enum, Variant.field)`.
3816+
FieldOf(&'hir Ty<'hir>, &'hir TyFieldPath),
38073817
/// `TyKind::Infer` means the type should be inferred instead of it having been
38083818
/// specified. This can appear anywhere in a type.
38093819
///

compiler/rustc_hir/src/intravisit.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -
10471047
try_visit!(visitor.visit_ty_unambig(ty));
10481048
try_visit!(visitor.visit_pattern_type_pattern(pat));
10491049
}
1050+
TyKind::FieldOf(ty, TyFieldPath { variant, field }) => {
1051+
try_visit!(visitor.visit_ty_unambig(ty));
1052+
visit_opt!(visitor, visit_ident, *variant);
1053+
try_visit!(visitor.visit_ident(*field));
1054+
}
10501055
}
10511056
V::Result::output()
10521057
}

0 commit comments

Comments
 (0)