Skip to content

Commit 297bdad

Browse files
committed
add FieldPath
1 parent 6202eac commit 297bdad

File tree

14 files changed

+195
-16
lines changed

14 files changed

+195
-16
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use std::ops::ControlFlow;
2+
3+
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
4+
use rustc_macros::{HashStable, TyEncodable};
5+
use rustc_span::{Symbol, sym};
6+
7+
use crate::ty::{self, List, Ty, TyCtxt};
8+
9+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10+
pub enum FieldPathKind {
11+
OffsetOf,
12+
FieldOf,
13+
}
14+
15+
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, TyEncodable)]
16+
pub struct FieldPath<'tcx>(pub &'tcx List<(VariantIdx, FieldIdx)>);
17+
18+
impl<'tcx> IntoIterator for FieldPath<'tcx> {
19+
type Item = <&'tcx List<(VariantIdx, FieldIdx)> as IntoIterator>::Item;
20+
21+
type IntoIter = <&'tcx List<(VariantIdx, FieldIdx)> as IntoIterator>::IntoIter;
22+
23+
fn into_iter(self) -> Self::IntoIter {
24+
self.0.into_iter()
25+
}
26+
}
27+
28+
impl<'tcx> IntoIterator for &FieldPath<'tcx> {
29+
type Item = <&'tcx List<(VariantIdx, FieldIdx)> as IntoIterator>::Item;
30+
31+
type IntoIter = <&'tcx List<(VariantIdx, FieldIdx)> as IntoIterator>::IntoIter;
32+
33+
fn into_iter(self) -> Self::IntoIter {
34+
self.0.into_iter()
35+
}
36+
}
37+
38+
impl<'tcx> FieldPath<'tcx> {
39+
pub fn iter(self) -> <Self as IntoIterator>::IntoIter {
40+
self.into_iter()
41+
}
42+
43+
pub fn walk<T>(
44+
self,
45+
tcx: TyCtxt<'tcx>,
46+
container: Ty<'tcx>,
47+
mut walker: impl FnMut(Ty<'tcx>, Symbol, Ty<'tcx>, bool) -> ControlFlow<T>,
48+
) -> Option<T> {
49+
let mut cur = container;
50+
for (i, (variant, field)) in self.iter().enumerate() {
51+
let last = i == self.0.len() - 1;
52+
let (name, field_ty) = match cur.kind() {
53+
ty::Adt(def, args) => {
54+
let variant = def.variant(variant);
55+
let field = &variant.fields[field];
56+
let field_ty = field.ty(tcx, args);
57+
(field.name, field_ty)
58+
}
59+
ty::Tuple(tys) => {
60+
assert_eq!(FIRST_VARIANT, variant);
61+
(sym::integer(field.index()), tys[field.index()])
62+
}
63+
_ => bug!("only ADTs and tuples are supported by `field_of!`, found {cur}"),
64+
};
65+
match walker(cur, name, field_ty, last) {
66+
ControlFlow::Break(val) => return Some(val),
67+
ControlFlow::Continue(()) => cur = field_ty,
68+
}
69+
}
70+
None
71+
}
72+
73+
pub fn field_ty(self, tcx: TyCtxt<'tcx>, container: Ty<'tcx>) -> Ty<'tcx> {
74+
self.walk(tcx, container, |_, _, ty, last| {
75+
if last { ControlFlow::Break(ty) } else { ControlFlow::Continue(()) }
76+
})
77+
.expect("field path to have a last segment")
78+
}
79+
}
80+
81+
impl<'tcx> rustc_type_ir::inherent::FieldPath<TyCtxt<'tcx>> for FieldPath<'tcx> {
82+
fn walk<T>(
83+
self,
84+
interner: TyCtxt<'tcx>,
85+
container: Ty<'tcx>,
86+
walker: impl FnMut(Ty<'tcx>, Symbol, Ty<'tcx>, bool) -> ControlFlow<T>,
87+
) -> Option<T> {
88+
self.walk(interner, container, walker)
89+
}
90+
91+
fn field_ty(self, interner: TyCtxt<'tcx>, container: Ty<'tcx>) -> Ty<'tcx> {
92+
self.field_ty(interner, container)
93+
}
94+
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub use self::context::{
8080
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
8181
TyCtxtFeed, tls,
8282
};
83+
pub use self::field_path::{FieldPath, FieldPathKind};
8384
pub use self::fold::*;
8485
pub use self::instance::{Instance, InstanceKind, ReifyReason, UnusedGenericParams};
8586
pub use self::list::{List, ListWithCachedTypeInfo};
@@ -147,6 +148,7 @@ mod context;
147148
mod diagnostics;
148149
mod elaborate_impl;
149150
mod erase_regions;
151+
mod field_path;
150152
mod fold;
151153
mod generic_args;
152154
mod generics;

compiler/rustc_public/src/abi.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::compiler_interface::with;
88
use crate::mir::FieldIdx;
99
use crate::target::{MachineInfo, MachineSize as Size};
1010
use crate::ty::{Align, Ty, VariantIdx};
11-
use crate::{Error, Opaque, error};
11+
use crate::{Error, IndexedVal, Opaque, error};
1212

1313
/// A function ABI definition.
1414
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
@@ -159,10 +159,13 @@ impl FieldsShape {
159159
pub fn fields_by_offset_order(&self) -> Vec<FieldIdx> {
160160
match self {
161161
FieldsShape::Primitive => vec![],
162-
FieldsShape::Union(_) | FieldsShape::Array { .. } => (0..self.count()).collect(),
162+
FieldsShape::Union(_) | FieldsShape::Array { .. } => {
163+
(0..self.count()).map(IndexedVal::to_val).collect()
164+
}
163165
FieldsShape::Arbitrary { offsets, .. } => {
164-
let mut indices = (0..offsets.len()).collect::<Vec<_>>();
165-
indices.sort_by_key(|idx| offsets[*idx]);
166+
let mut indices: Vec<FieldIdx> =
167+
(0..offsets.len()).map(IndexedVal::to_val).collect::<Vec<_>>();
168+
indices.sort_by_key(|idx| offsets[idx.to_index()]);
166169
indices
167170
}
168171
}
@@ -195,7 +198,7 @@ pub enum VariantsShape {
195198
Multiple {
196199
tag: Scalar,
197200
tag_encoding: TagEncoding,
198-
tag_field: usize,
201+
tag_field: FieldIdx,
199202
variants: Vec<LayoutShape>,
200203
},
201204
}

compiler/rustc_public/src/mir/body.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,24 @@ pub const RETURN_LOCAL: Local = 0;
871871
/// `b`'s `FieldIdx` is `1`,
872872
/// `c`'s `FieldIdx` is `0`, and
873873
/// `g`'s `FieldIdx` is `2`.
874-
pub type FieldIdx = usize;
874+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
875+
pub struct FieldIdx(pub usize);
876+
877+
impl crate::IndexedVal for FieldIdx {
878+
fn to_val(index: usize) -> Self {
879+
FieldIdx(index)
880+
}
881+
882+
fn to_index(&self) -> usize {
883+
self.0
884+
}
885+
}
886+
887+
impl From<FieldIdx> for rustc_abi::FieldIdx {
888+
fn from(value: FieldIdx) -> Self {
889+
value.0.into()
890+
}
891+
}
875892

876893
type UserTypeAnnotationIndex = usize;
877894

compiler/rustc_public/src/ty.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::mir::{Body, Mutability, Safety};
88
use super::{DefId, Error, Symbol, with};
99
use crate::abi::{FnAbi, Layout};
1010
use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType};
11+
use crate::mir::FieldIdx;
1112
use crate::mir::alloc::{AllocId, read_target_int, read_target_uint};
1213
use crate::mir::mono::StaticDef;
1314
use crate::target::MachineInfo;
@@ -1053,6 +1054,9 @@ impl GenericArgKind {
10531054
}
10541055
}
10551056

1057+
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
1058+
pub struct FieldPath(pub Vec<(VariantIdx, FieldIdx)>);
1059+
10561060
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
10571061
pub enum TermKind {
10581062
Type(Ty),

compiler/rustc_public/src/unstable/convert/internal.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ use crate::abi::Layout;
1212
use crate::compiler_interface::BridgeTys;
1313
use crate::mir::alloc::AllocId;
1414
use crate::mir::mono::{Instance, MonoItem, StaticDef};
15-
use crate::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp};
15+
use crate::mir::{BinOp, FieldIdx, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp};
1616
use crate::ty::{
1717
Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind,
18-
ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
18+
ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FieldPath, FloatTy, FnSig,
1919
GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span,
2020
TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx,
2121
};
@@ -82,6 +82,21 @@ impl RustcInternal for GenericArgKind {
8282
}
8383
}
8484

85+
impl RustcInternal for FieldPath {
86+
type T<'tcx> = rustc_ty::FieldPath<'tcx>;
87+
fn internal<'tcx>(
88+
&self,
89+
tables: &mut Tables<'_, BridgeTys>,
90+
tcx: impl InternalCx<'tcx>,
91+
) -> Self::T<'tcx> {
92+
tcx.tcx().mk_field_path_from_iter(
93+
self.0
94+
.iter()
95+
.map(|(var, field)| (var.internal(tables, tcx), field.internal(tables, tcx))),
96+
)
97+
}
98+
}
99+
85100
impl RustcInternal for Region {
86101
type T<'tcx> = rustc_ty::Region<'tcx>;
87102
fn internal<'tcx>(
@@ -343,6 +358,18 @@ impl RustcInternal for VariantDef {
343358
}
344359
}
345360

361+
impl RustcInternal for FieldIdx {
362+
type T<'tcx> = rustc_abi::FieldIdx;
363+
364+
fn internal<'tcx>(
365+
&self,
366+
_tables: &mut Tables<'_, BridgeTys>,
367+
_tcx: impl InternalCx<'tcx>,
368+
) -> Self::T<'tcx> {
369+
rustc_abi::FieldIdx::from(self.to_index())
370+
}
371+
}
372+
346373
impl RustcInternal for MirConst {
347374
type T<'tcx> = rustc_middle::mir::Const<'tcx>;
348375
fn internal<'tcx>(

compiler/rustc_public/src/unstable/convert/stable/mir.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use rustc_public_bridge::{Tables, bridge};
77

88
use crate::compiler_interface::BridgeTys;
99
use crate::mir::alloc::GlobalAlloc;
10-
use crate::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment};
10+
use crate::mir::{ConstOperand, FieldIdx, Statement, UserTypeProjection, VarDebugInfoFragment};
1111
use crate::ty::{Allocation, ConstantKind, MirConst};
1212
use crate::unstable::Stable;
13-
use crate::{Error, alloc, opaque};
13+
use crate::{Error, IndexedVal, alloc, opaque};
1414

1515
impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
1616
type T = crate::mir::Body;
@@ -642,7 +642,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
642642
var_idx.stable(tables, cx),
643643
generic_arg.stable(tables, cx),
644644
user_ty_index.map(|idx| idx.index()),
645-
field_idx.map(|idx| idx.index()),
645+
field_idx.map(|idx| FieldIdx::to_val(idx.index())),
646646
)
647647
}
648648
mir::AggregateKind::Closure(def_id, generic_arg) => crate::mir::AggregateKind::Closure(

compiler/rustc_public/src/unstable/convert/stable/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_public_bridge::Tables;
55
use rustc_public_bridge::context::CompilerCtxt;
66

77
use super::Stable;
8+
use crate::IndexedVal;
89
use crate::compiler_interface::BridgeTys;
910

1011
mod abi;
@@ -22,9 +23,9 @@ impl<'tcx> Stable<'tcx> for rustc_hir::Safety {
2223
}
2324

2425
impl<'tcx> Stable<'tcx> for FieldIdx {
25-
type T = usize;
26+
type T = crate::mir::FieldIdx;
2627
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
27-
self.as_usize()
28+
crate::mir::FieldIdx::to_val(self.as_usize())
2829
}
2930
}
3031

compiler/rustc_public/src/unstable/convert/stable/ty.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,22 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
686686
}
687687
}
688688

689+
impl<'tcx> Stable<'tcx> for rustc_middle::ty::FieldPath<'tcx> {
690+
type T = crate::ty::FieldPath;
691+
692+
fn stable<'cx>(
693+
&self,
694+
tables: &mut Tables<'cx, BridgeTys>,
695+
cx: &CompilerCtxt<'cx, BridgeTys>,
696+
) -> Self::T {
697+
crate::ty::FieldPath(
698+
self.into_iter()
699+
.map(|(var, field)| (var.stable(tables, cx), field.stable(tables, cx)))
700+
.collect(),
701+
)
702+
}
703+
}
704+
689705
impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
690706
type T = crate::ty::PredicateKind;
691707

compiler/rustc_type_ir/src/inherent.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,17 @@ pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
630630
fn destructor(self, interner: I) -> Option<AdtDestructorKind>;
631631
}
632632

633+
pub trait FieldPath<I: Interner>: Copy + Debug + Hash + Eq {
634+
fn walk<T>(
635+
self,
636+
interner: I,
637+
container: I::Ty,
638+
walker: impl FnMut(I::Ty, I::Symbol, I::Ty, bool) -> ControlFlow<T>,
639+
) -> Option<T>;
640+
641+
fn field_ty(self, interner: I, container: I::Ty) -> I::Ty;
642+
}
643+
633644
pub trait ParamEnv<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
634645
fn caller_bounds(self) -> impl SliceLike<Item = I::Clause>;
635646
}

0 commit comments

Comments
 (0)