Skip to content

Commit 3b11007

Browse files
committed
Enums in offset_of: update based on est31, scottmcm & llogiq review
1 parent 825bb5a commit 3b11007

File tree

15 files changed

+150
-140
lines changed

15 files changed

+150
-140
lines changed

compiler/rustc_abi/src/lib.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1119,13 +1119,6 @@ rustc_index::newtype_index! {
11191119
pub struct FieldIdx {}
11201120
}
11211121

1122-
/// `offset_of` can traverse fields and enum variants and should keep track of which is which.
1123-
#[derive(Copy, Clone, Debug, Eq, Hash, HashStable_Generic, PartialEq, Encodable, Decodable)]
1124-
pub enum OffsetOfIdx {
1125-
Field(FieldIdx),
1126-
Variant(VariantIdx),
1127-
}
1128-
11291122
/// Describes how the fields of a type are located in memory.
11301123
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
11311124
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]

compiler/rustc_const_eval/src/transform/validate.rs

+12-24
Original file line numberDiff line numberDiff line change
@@ -971,37 +971,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
971971
};
972972

973973
let mut current_ty = *container;
974-
let mut indices = indices.into_iter();
975974

976-
use rustc_target::abi::OffsetOfIdx::*;
977-
978-
while let Some(index) = indices.next() {
979-
match (current_ty.kind(), index) {
980-
(ty::Tuple(fields), Field(field)) => {
981-
let Some(&f_ty) = fields.get(field.as_usize()) else {
982-
fail_out_of_bounds(self, location, field, current_ty);
975+
for (variant, field) in indices.iter() {
976+
match current_ty.kind() {
977+
ty::Tuple(fields) => {
978+
if variant != FIRST_VARIANT {
979+
self.fail(
980+
location,
981+
format!("tried to get variant {variant:?} of tuple"),
982+
);
983983
return;
984-
};
985-
986-
current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
987-
}
988-
(ty::Adt(adt_def, args), Field(field)) if !adt_def.is_enum() => {
989-
let Some(field) = adt_def.non_enum_variant().fields.get(field) else {
984+
}
985+
let Some(&f_ty) = fields.get(field.as_usize()) else {
990986
fail_out_of_bounds(self, location, field, current_ty);
991987
return;
992988
};
993989

994-
let f_ty = field.ty(self.tcx, args);
995990
current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
996991
}
997-
(ty::Adt(adt_def, args), Variant(variant)) if adt_def.is_enum() => {
998-
let Some(Field(field)) = indices.next() else {
999-
self.fail(
1000-
location,
1001-
format!("enum variant must be followed by field index in offset_of; in {current_ty:?}"),
1002-
);
1003-
return;
1004-
};
992+
ty::Adt(adt_def, args) => {
1005993
let Some(field) = adt_def.variant(variant).fields.get(field) else {
1006994
fail_out_of_bounds(self, location, field, current_ty);
1007995
return;
@@ -1013,7 +1001,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
10131001
_ => {
10141002
self.fail(
10151003
location,
1016-
format!("Cannot get offset {index:?} from type {current_ty:?}"),
1004+
format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"),
10171005
);
10181006
return;
10191007
}

compiler/rustc_hir_typeck/src/expr.rs

+59-42
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
5252
use rustc_span::hygiene::DesugaringKind;
5353
use rustc_span::source_map::{Span, Spanned};
5454
use rustc_span::symbol::{kw, sym, Ident, Symbol};
55-
use rustc_target::abi::FieldIdx;
55+
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
5656
use rustc_target::spec::abi::Abi::RustIntrinsic;
5757
use rustc_trait_selection::infer::InferCtxtExt;
5858
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -3128,8 +3128,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31283128
fields: &[Ident],
31293129
expr: &'tcx hir::Expr<'tcx>,
31303130
) -> Ty<'tcx> {
3131-
use rustc_target::abi::OffsetOfIdx::*;
3132-
31333131
let container = self.to_ty(container).normalized;
31343132

31353133
let mut field_indices = Vec::with_capacity(fields.len());
@@ -3145,49 +3143,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31453143
let (ident, _def_scope) =
31463144
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
31473145

3148-
if let Some((index, variant)) = container_def.variants()
3146+
let Some((index, variant)) = container_def.variants()
31493147
.iter_enumerated()
3150-
.find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident)
3151-
{
3152-
let Some(&subfield) = fields.next() else {
3153-
let mut err = type_error_struct!(
3154-
self.tcx().sess,
3155-
ident.span,
3156-
container,
3157-
E0795,
3158-
"`{ident}` is an enum variant; expected field at end of `offset_of`",
3159-
);
3160-
err.span_label(field.span, "enum variant");
3161-
err.emit();
3162-
break;
3163-
};
3164-
let (subident, sub_def_scope) =
3165-
self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block);
3166-
3167-
if let Some((subindex, field)) = variant.fields
3168-
.iter_enumerated()
3169-
.find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident)
3170-
{
3171-
let field_ty = self.field_ty(expr.span, field, args);
3148+
.find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else {
3149+
let mut err = type_error_struct!(
3150+
self.tcx().sess,
3151+
ident.span,
3152+
container,
3153+
E0599,
3154+
"no variant named `{ident}` found for enum `{container}`",
3155+
);
3156+
err.span_label(field.span, "variant not found");
3157+
err.emit();
3158+
break;
3159+
};
3160+
let Some(&subfield) = fields.next() else {
3161+
let mut err = type_error_struct!(
3162+
self.tcx().sess,
3163+
ident.span,
3164+
container,
3165+
E0795,
3166+
"`{ident}` is an enum variant; expected field at end of `offset_of`",
3167+
);
3168+
err.span_label(field.span, "enum variant");
3169+
err.emit();
3170+
break;
3171+
};
3172+
let (subident, sub_def_scope) =
3173+
self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block);
31723174

3173-
// FIXME: DSTs with static alignment should be allowed
3174-
self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
3175+
let Some((subindex, field)) = variant.fields
3176+
.iter_enumerated()
3177+
.find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) else {
3178+
let mut err = type_error_struct!(
3179+
self.tcx().sess,
3180+
ident.span,
3181+
container,
3182+
E0609,
3183+
"no field named `{subfield}` on enum variant `{container}::{ident}`",
3184+
);
3185+
err.span_label(field.span, "this enum variant...");
3186+
err.span_label(subident.span, "...does not have this field");
3187+
err.emit();
3188+
break;
3189+
};
31753190

3176-
if field.vis.is_accessible_from(sub_def_scope, self.tcx) {
3177-
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
3178-
} else {
3179-
self.private_field_err(ident, container_def.did()).emit();
3180-
}
3191+
let field_ty = self.field_ty(expr.span, field, args);
31813192

3182-
// Save the index of all fields regardless of their visibility in case
3183-
// of error recovery.
3184-
field_indices.push(Variant(index));
3185-
field_indices.push(Field(subindex));
3186-
current_container = field_ty;
3193+
// FIXME: DSTs with static alignment should be allowed
3194+
self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
31873195

3188-
continue;
3189-
}
3196+
if field.vis.is_accessible_from(sub_def_scope, self.tcx) {
3197+
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
3198+
} else {
3199+
self.private_field_err(ident, container_def.did()).emit();
31903200
}
3201+
3202+
// Save the index of all fields regardless of their visibility in case
3203+
// of error recovery.
3204+
field_indices.push((index, subindex));
3205+
current_container = field_ty;
3206+
3207+
continue;
31913208
}
31923209
ty::Adt(container_def, args) => {
31933210
let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
@@ -3212,7 +3229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32123229

32133230
// Save the index of all fields regardless of their visibility in case
32143231
// of error recovery.
3215-
field_indices.push(Field(index));
3232+
field_indices.push((FIRST_VARIANT, index));
32163233
current_container = field_ty;
32173234

32183235
continue;
@@ -3226,7 +3243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32263243
self.require_type_is_sized(ty, expr.span, traits::MiscObligation);
32273244
}
32283245
if let Some(&field_ty) = tys.get(index) {
3229-
field_indices.push(Field(index.into()));
3246+
field_indices.push((FIRST_VARIANT, index.into()));
32303247
current_container = field_ty;
32313248

32323249
continue;

compiler/rustc_middle/src/mir/syntax.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_hir::def_id::DefId;
1717
use rustc_hir::{self as hir};
1818
use rustc_hir::{self, GeneratorKind};
1919
use rustc_index::IndexVec;
20-
use rustc_target::abi::{FieldIdx, OffsetOfIdx, VariantIdx};
20+
use rustc_target::abi::{FieldIdx, VariantIdx};
2121

2222
use rustc_ast::Mutability;
2323
use rustc_span::def_id::LocalDefId;
@@ -1281,7 +1281,7 @@ pub enum NullOp<'tcx> {
12811281
/// Returns the minimum alignment of a type
12821282
AlignOf,
12831283
/// Returns the offset of a field
1284-
OffsetOf(&'tcx List<OffsetOfIdx>),
1284+
OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
12851285
}
12861286

12871287
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]

compiler/rustc_middle/src/thir.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarArgs};
2424
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
2525
use rustc_span::def_id::LocalDefId;
2626
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
27-
use rustc_target::abi::{FieldIdx, OffsetOfIdx, VariantIdx};
27+
use rustc_target::abi::{FieldIdx, VariantIdx};
2828
use rustc_target::asm::InlineAsmRegOrRegClass;
2929
use std::fmt;
3030
use std::ops::Index;
@@ -488,7 +488,7 @@ pub enum ExprKind<'tcx> {
488488
/// Field offset (`offset_of!`)
489489
OffsetOf {
490490
container: Ty<'tcx>,
491-
fields: &'tcx List<OffsetOfIdx>,
491+
fields: &'tcx List<(VariantIdx, FieldIdx)>,
492492
},
493493
/// An expression taking a reference to a thread local.
494494
ThreadLocalRef(DefId),

compiler/rustc_middle/src/ty/codec.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_data_structures::fx::FxHashMap;
1919
use rustc_middle::ty::TyCtxt;
2020
use rustc_serialize::{Decodable, Encodable};
2121
use rustc_span::Span;
22-
use rustc_target::abi::{FieldIdx, OffsetOfIdx};
22+
use rustc_target::abi::{FieldIdx, VariantIdx};
2323
pub use rustc_type_ir::{TyDecoder, TyEncoder};
2424
use std::hash::Hash;
2525
use std::intrinsics;
@@ -412,12 +412,14 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Fi
412412
}
413413
}
414414

415-
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<OffsetOfIdx> {
415+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
416+
for ty::List<(VariantIdx, FieldIdx)>
417+
{
416418
fn decode(decoder: &mut D) -> &'tcx Self {
417419
let len = decoder.read_usize();
418-
decoder
419-
.interner()
420-
.mk_offset_of_from_iter((0..len).map::<OffsetOfIdx, _>(|_| Decodable::decode(decoder)))
420+
decoder.interner().mk_offset_of_from_iter(
421+
(0..len).map::<(VariantIdx, FieldIdx), _>(|_| Decodable::decode(decoder)),
422+
)
421423
}
422424
}
423425

@@ -433,7 +435,7 @@ impl_decodable_via_ref! {
433435
&'tcx ty::List<ty::BoundVariableKind>,
434436
&'tcx ty::List<ty::Clause<'tcx>>,
435437
&'tcx ty::List<FieldIdx>,
436-
&'tcx ty::List<OffsetOfIdx>,
438+
&'tcx ty::List<(VariantIdx, FieldIdx)>,
437439
}
438440

439441
#[macro_export]

compiler/rustc_middle/src/ty/context.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ use rustc_session::{Limit, MetadataKind, Session};
6363
use rustc_span::def_id::{DefPathHash, StableCrateId};
6464
use rustc_span::symbol::{kw, sym, Ident, Symbol};
6565
use rustc_span::{Span, DUMMY_SP};
66-
use rustc_target::abi::{FieldIdx, Layout, LayoutS, OffsetOfIdx, TargetDataLayout, VariantIdx};
66+
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
6767
use rustc_target::spec::abi;
6868
use rustc_type_ir::sty::TyKind::*;
6969
use rustc_type_ir::WithCachedTypeInfo;
@@ -156,7 +156,7 @@ pub struct CtxtInterners<'tcx> {
156156
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
157157
predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
158158
fields: InternedSet<'tcx, List<FieldIdx>>,
159-
offset_of: InternedSet<'tcx, List<OffsetOfIdx>>,
159+
offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
160160
}
161161

162162
impl<'tcx> CtxtInterners<'tcx> {
@@ -1538,7 +1538,7 @@ slice_interners!(
15381538
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
15391539
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
15401540
fields: pub mk_fields(FieldIdx),
1541-
offset_of: pub mk_offset_of(OffsetOfIdx),
1541+
offset_of: pub mk_offset_of((VariantIdx, FieldIdx)),
15421542
);
15431543

15441544
impl<'tcx> TyCtxt<'tcx> {
@@ -1863,7 +1863,7 @@ impl<'tcx> TyCtxt<'tcx> {
18631863
pub fn mk_offset_of_from_iter<I, T>(self, iter: I) -> T::Output
18641864
where
18651865
I: Iterator<Item = T>,
1866-
T: CollectAndApply<OffsetOfIdx, &'tcx List<OffsetOfIdx>>,
1866+
T: CollectAndApply<(VariantIdx, FieldIdx), &'tcx List<(VariantIdx, FieldIdx)>>,
18671867
{
18681868
T::collect_and_apply(iter, |xs| self.mk_offset_of(xs))
18691869
}

compiler/rustc_middle/src/ty/typeck_results.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_macros::HashStable;
2424
use rustc_middle::mir::FakeReadCause;
2525
use rustc_session::Session;
2626
use rustc_span::Span;
27-
use rustc_target::abi::{FieldIdx, OffsetOfIdx};
27+
use rustc_target::abi::{FieldIdx, VariantIdx};
2828
use std::{collections::hash_map::Entry, hash::Hash, iter};
2929

3030
use super::RvalueScopes;
@@ -209,7 +209,7 @@ pub struct TypeckResults<'tcx> {
209209
pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
210210

211211
/// Container types and field indices of `offset_of!` expressions
212-
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<OffsetOfIdx>)>,
212+
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
213213
}
214214

215215
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
@@ -534,13 +534,15 @@ impl<'tcx> TypeckResults<'tcx> {
534534
&self.coercion_casts
535535
}
536536

537-
pub fn offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<OffsetOfIdx>)> {
537+
pub fn offset_of_data(
538+
&self,
539+
) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
538540
LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
539541
}
540542

541543
pub fn offset_of_data_mut(
542544
&mut self,
543-
) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<OffsetOfIdx>)> {
545+
) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
544546
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
545547
}
546548
}

0 commit comments

Comments
 (0)