Skip to content

Commit 146dafa

Browse files
committedNov 1, 2023
Auto merge of #114208 - GKFX:offset_of_enum, r=wesleywiser
Support enum variants in offset_of! This MR implements support for navigating through enum variants in `offset_of!`, placing the enum variant name in the second argument to `offset_of!`. The RFC placed it in the first argument, but I think it interacts better with nested field access in the second, as you can then write things like ```rust offset_of!(Type, field.Variant.field) ``` Alternatively, a syntactic distinction could be made between variants and fields (e.g. `field::Variant.field`) but I'm not convinced this would be helpful. [RFC 3308 # Enum Support](https://rust-lang.github.io/rfcs/3308-offset_of.html#enum-support-offset_ofsomeenumstructvariant-field_on_variant) Tracking Issue #106655.
·
1.88.01.75.0
2 parents 11cd1f0 + e742f80 commit 146dafa

File tree

33 files changed

+477
-89
lines changed

33 files changed

+477
-89
lines changed
 

‎compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ fn codegen_stmt<'tcx>(
766766
NullOp::SizeOf => layout.size.bytes(),
767767
NullOp::AlignOf => layout.align.abi.bytes(),
768768
NullOp::OffsetOf(fields) => {
769-
layout.offset_of_subfield(fx, fields.iter().map(|f| f.index())).bytes()
769+
layout.offset_of_subfield(fx, fields.iter()).bytes()
770770
}
771771
};
772772
let val = CValue::by_val(

‎compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
680680
layout.align.abi.bytes()
681681
}
682682
mir::NullOp::OffsetOf(fields) => {
683-
layout.offset_of_subfield(bx.cx(), fields.iter().map(|f| f.index())).bytes()
683+
layout.offset_of_subfield(bx.cx(), fields.iter()).bytes()
684684
}
685685
};
686686
let val = bx.cx().const_usize(val);

‎compiler/rustc_const_eval/src/interpret/step.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
275275
mir::NullOp::SizeOf => layout.size.bytes(),
276276
mir::NullOp::AlignOf => layout.align.abi.bytes(),
277277
mir::NullOp::OffsetOf(fields) => {
278-
layout.offset_of_subfield(self, fields.iter().map(|f| f.index())).bytes()
278+
layout.offset_of_subfield(self, fields.iter()).bytes()
279279
}
280280
};
281281
self.write_scalar(Scalar::from_target_usize(val, self), &dest)?;

‎compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,16 +1056,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
10561056
}
10571057
}
10581058
}
1059-
Rvalue::NullaryOp(NullOp::OffsetOf(fields), container) => {
1059+
Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => {
10601060
let fail_out_of_bounds = |this: &mut Self, location, field, ty| {
10611061
this.fail(location, format!("Out of bounds field {field:?} for {ty:?}"));
10621062
};
10631063

10641064
let mut current_ty = *container;
10651065

1066-
for field in fields.iter() {
1066+
for (variant, field) in indices.iter() {
10671067
match current_ty.kind() {
10681068
ty::Tuple(fields) => {
1069+
if variant != FIRST_VARIANT {
1070+
self.fail(
1071+
location,
1072+
format!("tried to get variant {variant:?} of tuple"),
1073+
);
1074+
return;
1075+
}
10691076
let Some(&f_ty) = fields.get(field.as_usize()) else {
10701077
fail_out_of_bounds(self, location, field, current_ty);
10711078
return;
@@ -1074,15 +1081,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
10741081
current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
10751082
}
10761083
ty::Adt(adt_def, args) => {
1077-
if adt_def.is_enum() {
1078-
self.fail(
1079-
location,
1080-
format!("Cannot get field offset from enum {current_ty:?}"),
1081-
);
1082-
return;
1083-
}
1084-
1085-
let Some(field) = adt_def.non_enum_variant().fields.get(field) else {
1084+
let Some(field) = adt_def.variant(variant).fields.get(field) else {
10861085
fail_out_of_bounds(self, location, field, current_ty);
10871086
return;
10881087
};
@@ -1093,7 +1092,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
10931092
_ => {
10941093
self.fail(
10951094
location,
1096-
format!("Cannot get field offset from non-adt type {current_ty:?}"),
1095+
format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"),
10971096
);
10981097
return;
10991098
}

‎compiler/rustc_error_codes/src/error_codes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ E0791: include_str!("./error_codes/E0791.md"),
514514
E0792: include_str!("./error_codes/E0792.md"),
515515
E0793: include_str!("./error_codes/E0793.md"),
516516
E0794: include_str!("./error_codes/E0794.md"),
517+
E0795: include_str!("./error_codes/E0795.md"),
517518
}
518519

519520
// Undocumented removed error codes. Note that many removed error codes are kept in the list above
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Invalid argument for the `offset_of!` macro.
2+
3+
Erroneous code example:
4+
5+
```compile_fail,E0795
6+
#![feature(offset_of)]
7+
8+
let x = std::mem::offset_of!(Option<u8>, Some);
9+
```
10+
11+
The `offset_of!` macro gives the offset of a field within a type. It can
12+
navigate through enum variants, but the final component of its second argument
13+
must be a field and not a variant.
14+
15+
The offset of the contained `u8` in the `Option<u8>` can be found by specifying
16+
the field name `0`:
17+
18+
```
19+
#![feature(offset_of)]
20+
21+
let x: usize = std::mem::offset_of!(Option<u8>, Some.0);
22+
```
23+
24+
The discriminant of an enumeration may be read with `core::mem::discriminant`,
25+
but this is not always a value physically present within the enum.
26+
27+
Further information about enum layout may be found at
28+
https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html.

‎compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
5454
use rustc_span::hygiene::DesugaringKind;
5555
use rustc_span::source_map::{Span, Spanned};
5656
use rustc_span::symbol::{kw, sym, Ident, Symbol};
57-
use rustc_target::abi::FieldIdx;
57+
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
5858
use rustc_target::spec::abi::Abi::RustIntrinsic;
5959
use rustc_trait_selection::infer::InferCtxtExt;
6060
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -3107,12 +3107,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31073107

31083108
let mut field_indices = Vec::with_capacity(fields.len());
31093109
let mut current_container = container;
3110+
let mut fields = fields.into_iter();
31103111

3111-
for &field in fields {
3112+
while let Some(&field) = fields.next() {
31123113
let container = self.structurally_resolve_type(expr.span, current_container);
31133114

31143115
match container.kind() {
3115-
ty::Adt(container_def, args) if !container_def.is_enum() => {
3116+
ty::Adt(container_def, args) if container_def.is_enum() => {
3117+
let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
3118+
let (ident, _def_scope) =
3119+
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
3120+
3121+
let Some((index, variant)) = container_def.variants()
3122+
.iter_enumerated()
3123+
.find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else {
3124+
let mut err = type_error_struct!(
3125+
self.tcx().sess,
3126+
ident.span,
3127+
container,
3128+
E0599,
3129+
"no variant named `{ident}` found for enum `{container}`",
3130+
);
3131+
err.span_label(field.span, "variant not found");
3132+
err.emit();
3133+
break;
3134+
};
3135+
let Some(&subfield) = fields.next() else {
3136+
let mut err = type_error_struct!(
3137+
self.tcx().sess,
3138+
ident.span,
3139+
container,
3140+
E0795,
3141+
"`{ident}` is an enum variant; expected field at end of `offset_of`",
3142+
);
3143+
err.span_label(field.span, "enum variant");
3144+
err.emit();
3145+
break;
3146+
};
3147+
let (subident, sub_def_scope) =
3148+
self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block);
3149+
3150+
let Some((subindex, field)) = variant.fields
3151+
.iter_enumerated()
3152+
.find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) else {
3153+
let mut err = type_error_struct!(
3154+
self.tcx().sess,
3155+
ident.span,
3156+
container,
3157+
E0609,
3158+
"no field named `{subfield}` on enum variant `{container}::{ident}`",
3159+
);
3160+
err.span_label(field.span, "this enum variant...");
3161+
err.span_label(subident.span, "...does not have this field");
3162+
err.emit();
3163+
break;
3164+
};
3165+
3166+
let field_ty = self.field_ty(expr.span, field, args);
3167+
3168+
// FIXME: DSTs with static alignment should be allowed
3169+
self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
3170+
3171+
if field.vis.is_accessible_from(sub_def_scope, self.tcx) {
3172+
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
3173+
} else {
3174+
self.private_field_err(ident, container_def.did()).emit();
3175+
}
3176+
3177+
// Save the index of all fields regardless of their visibility in case
3178+
// of error recovery.
3179+
field_indices.push((index, subindex));
3180+
current_container = field_ty;
3181+
3182+
continue;
3183+
}
3184+
ty::Adt(container_def, args) => {
31163185
let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
31173186
let (ident, def_scope) =
31183187
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
@@ -3135,7 +3204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31353204

31363205
// Save the index of all fields regardless of their visibility in case
31373206
// of error recovery.
3138-
field_indices.push(index);
3207+
field_indices.push((FIRST_VARIANT, index));
31393208
current_container = field_ty;
31403209

31413210
continue;
@@ -3149,7 +3218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31493218
self.require_type_is_sized(ty, expr.span, traits::MiscObligation);
31503219
}
31513220
if let Some(&field_ty) = tys.get(index) {
3152-
field_indices.push(index.into());
3221+
field_indices.push((FIRST_VARIANT, index.into()));
31533222
current_container = field_ty;
31543223

31553224
continue;

‎compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1354,7 +1354,7 @@ pub enum NullOp<'tcx> {
13541354
/// Returns the minimum alignment of a type
13551355
AlignOf,
13561356
/// Returns the offset of a field
1357-
OffsetOf(&'tcx List<FieldIdx>),
1357+
OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
13581358
}
13591359

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

‎compiler/rustc_middle/src/thir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ pub enum ExprKind<'tcx> {
492492
/// Field offset (`offset_of!`)
493493
OffsetOf {
494494
container: Ty<'tcx>,
495-
fields: &'tcx List<FieldIdx>,
495+
fields: &'tcx List<(VariantIdx, FieldIdx)>,
496496
},
497497
/// An expression taking a reference to a thread local.
498498
ThreadLocalRef(DefId),

‎compiler/rustc_middle/src/ty/codec.rs

Lines changed: 13 additions & 1 deletion
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;
22+
use rustc_target::abi::{FieldIdx, VariantIdx};
2323
pub use rustc_type_ir::{TyDecoder, TyEncoder};
2424
use std::hash::Hash;
2525
use std::intrinsics;
@@ -414,6 +414,17 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Fi
414414
}
415415
}
416416

417+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
418+
for ty::List<(VariantIdx, FieldIdx)>
419+
{
420+
fn decode(decoder: &mut D) -> &'tcx Self {
421+
let len = decoder.read_usize();
422+
decoder.interner().mk_offset_of_from_iter(
423+
(0..len).map::<(VariantIdx, FieldIdx), _>(|_| Decodable::decode(decoder)),
424+
)
425+
}
426+
}
427+
417428
impl_decodable_via_ref! {
418429
&'tcx ty::TypeckResults<'tcx>,
419430
&'tcx ty::List<Ty<'tcx>>,
@@ -426,6 +437,7 @@ impl_decodable_via_ref! {
426437
&'tcx ty::List<ty::BoundVariableKind>,
427438
&'tcx ty::List<ty::Clause<'tcx>>,
428439
&'tcx ty::List<FieldIdx>,
440+
&'tcx ty::List<(VariantIdx, FieldIdx)>,
429441
}
430442

431443
#[macro_export]

‎compiler/rustc_middle/src/ty/context.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ pub struct CtxtInterners<'tcx> {
163163
predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
164164
fields: InternedSet<'tcx, List<FieldIdx>>,
165165
local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
166+
offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
166167
}
167168

168169
impl<'tcx> CtxtInterners<'tcx> {
@@ -189,6 +190,7 @@ impl<'tcx> CtxtInterners<'tcx> {
189190
predefined_opaques_in_body: Default::default(),
190191
fields: Default::default(),
191192
local_def_ids: Default::default(),
193+
offset_of: Default::default(),
192194
}
193195
}
194196

@@ -1587,6 +1589,7 @@ slice_interners!(
15871589
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
15881590
fields: pub mk_fields(FieldIdx),
15891591
local_def_ids: intern_local_def_ids(LocalDefId),
1592+
offset_of: pub mk_offset_of((VariantIdx, FieldIdx)),
15901593
);
15911594

15921595
impl<'tcx> TyCtxt<'tcx> {
@@ -1914,6 +1917,14 @@ impl<'tcx> TyCtxt<'tcx> {
19141917
T::collect_and_apply(iter, |xs| self.mk_fields(xs))
19151918
}
19161919

1920+
pub fn mk_offset_of_from_iter<I, T>(self, iter: I) -> T::Output
1921+
where
1922+
I: Iterator<Item = T>,
1923+
T: CollectAndApply<(VariantIdx, FieldIdx), &'tcx List<(VariantIdx, FieldIdx)>>,
1924+
{
1925+
T::collect_and_apply(iter, |xs| self.mk_offset_of(xs))
1926+
}
1927+
19171928
pub fn mk_args_trait(
19181929
self,
19191930
self_ty: Ty<'tcx>,

‎compiler/rustc_middle/src/ty/typeck_results.rs

Lines changed: 8 additions & 4 deletions
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;
27+
use rustc_target::abi::{FieldIdx, VariantIdx};
2828
use std::{collections::hash_map::Entry, hash::Hash, iter};
2929

3030
use super::RvalueScopes;
@@ -205,7 +205,7 @@ pub struct TypeckResults<'tcx> {
205205
pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
206206

207207
/// Container types and field indices of `offset_of!` expressions
208-
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
208+
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
209209
}
210210

211211
impl<'tcx> TypeckResults<'tcx> {
@@ -464,11 +464,15 @@ impl<'tcx> TypeckResults<'tcx> {
464464
&self.coercion_casts
465465
}
466466

467-
pub fn offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
467+
pub fn offset_of_data(
468+
&self,
469+
) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
468470
LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
469471
}
470472

471-
pub fn offset_of_data_mut(&mut self) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
473+
pub fn offset_of_data_mut(
474+
&mut self,
475+
) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
472476
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
473477
}
474478
}

‎compiler/rustc_mir_build/src/thir/cx/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ impl<'tcx> Cx<'tcx> {
670670
hir::ExprKind::OffsetOf(_, _) => {
671671
let data = self.typeck_results.offset_of_data();
672672
let &(container, ref indices) = data.get(expr.hir_id).unwrap();
673-
let fields = tcx.mk_fields_from_iter(indices.iter().copied());
673+
let fields = tcx.mk_offset_of_from_iter(indices.iter().copied());
674674

675675
ExprKind::OffsetOf { container, fields }
676676
}

‎compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
286286
let val = match null_op {
287287
NullOp::SizeOf if layout.is_sized() => layout.size.bytes(),
288288
NullOp::AlignOf if layout.is_sized() => layout.align.abi.bytes(),
289-
NullOp::OffsetOf(fields) => layout
290-
.offset_of_subfield(&self.ecx, fields.iter().map(|f| f.index()))
291-
.bytes(),
289+
NullOp::OffsetOf(fields) => {
290+
layout.offset_of_subfield(&self.ecx, fields.iter()).bytes()
291+
}
292292
_ => return ValueOrPlace::Value(FlatSet::Top),
293293
};
294294
FlatSet::Elem(Scalar::from_target_usize(val, &self.tcx))

‎compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -467,9 +467,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
467467
let val = match null_op {
468468
NullOp::SizeOf => layout.size.bytes(),
469469
NullOp::AlignOf => layout.align.abi.bytes(),
470-
NullOp::OffsetOf(fields) => layout
471-
.offset_of_subfield(&self.ecx, fields.iter().map(|f| f.index()))
472-
.bytes(),
470+
NullOp::OffsetOf(fields) => {
471+
layout.offset_of_subfield(&self.ecx, fields.iter()).bytes()
472+
}
473473
};
474474
let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
475475
let imm = ImmTy::try_from_uint(val, usize_layout)?;

‎compiler/rustc_passes/src/dead.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
257257

258258
let mut current_ty = container;
259259

260-
for &index in indices {
260+
for &(variant, field) in indices {
261261
match current_ty.kind() {
262262
ty::Adt(def, subst) => {
263-
let field = &def.non_enum_variant().fields[index];
263+
let field = &def.variant(variant).fields[field];
264264

265265
self.insert_def_id(field.did);
266266
let field_ty = field.ty(self.tcx, subst);
@@ -271,7 +271,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
271271
// but we may need to mark subfields
272272
ty::Tuple(tys) => {
273273
current_ty =
274-
self.tcx.normalize_erasing_regions(param_env, tys[index.as_usize()]);
274+
self.tcx.normalize_erasing_regions(param_env, tys[field.as_usize()]);
275275
}
276276
_ => span_bug!(expr.span, "named field access on non-ADT"),
277277
}

‎compiler/rustc_smir/src/rustc_smir/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,13 @@ impl<'tcx> Stable<'tcx> for FieldIdx {
649649
}
650650
}
651651

652+
impl<'tcx> Stable<'tcx> for (rustc_target::abi::VariantIdx, FieldIdx) {
653+
type T = (usize, usize);
654+
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
655+
(self.0.as_usize(), self.1.as_usize())
656+
}
657+
}
658+
652659
impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
653660
type T = stable_mir::mir::Operand;
654661
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {

‎compiler/rustc_target/src/abi/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,17 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
250250
Ty::is_transparent(self)
251251
}
252252

253-
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
253+
pub fn offset_of_subfield<C, I>(self, cx: &C, indices: I) -> Size
254254
where
255255
Ty: TyAbiInterface<'a, C>,
256+
I: Iterator<Item = (VariantIdx, FieldIdx)>,
256257
{
257258
let mut layout = self;
258259
let mut offset = Size::ZERO;
259260

260-
for index in indices {
261+
for (variant, field) in indices {
262+
layout = layout.for_variant(cx, variant);
263+
let index = field.index();
261264
offset += layout.fields.offset(index);
262265
layout = layout.field(cx, index);
263266
assert!(

‎compiler/stable_mir/src/mir/body.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ pub enum NullOp {
516516
/// Returns the minimum alignment of a type.
517517
AlignOf,
518518
/// Returns the offset of a field.
519-
OffsetOf(Vec<FieldIdx>),
519+
OffsetOf(Vec<(VariantIdx, FieldIdx)>),
520520
}
521521

522522
impl Operand {

‎library/core/src/mem/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,11 +1292,15 @@ impl<T> SizedTypeProperties for T {}
12921292

12931293
/// Expands to the offset in bytes of a field from the beginning of the given type.
12941294
///
1295-
/// Only structs, unions and tuples are supported.
1295+
/// Structs, enums, unions and tuples are supported.
12961296
///
12971297
/// Nested field accesses may be used, but not array indexes like in `C`'s `offsetof`.
12981298
///
1299-
/// Note that the output of this macro is not stable, except for `#[repr(C)]` types.
1299+
/// Enum variants may be traversed as if they were fields. Variants themselves do
1300+
/// not have an offset.
1301+
///
1302+
/// Note that type layout is, in general, [subject to change and
1303+
/// platform-specific](https://doc.rust-lang.org/reference/type-layout.html).
13001304
///
13011305
/// # Examples
13021306
///
@@ -1324,6 +1328,9 @@ impl<T> SizedTypeProperties for T {}
13241328
/// struct NestedB(u8);
13251329
///
13261330
/// assert_eq!(mem::offset_of!(NestedA, b.0), 0);
1331+
///
1332+
/// # #[cfg(not(bootstrap))]
1333+
/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
13271334
/// ```
13281335
#[unstable(feature = "offset_of", issue = "106655")]
13291336
#[allow_internal_unstable(builtin_syntax, hint_must_use)]

‎tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-abort.diff

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
let mut _4: usize;
99
let mut _6: usize;
1010
let mut _8: usize;
11+
let mut _10: usize;
12+
let mut _12: usize;
13+
let mut _14: usize;
1114
scope 1 {
1215
debug x => _1;
1316
let _3: usize;
@@ -19,6 +22,18 @@
1922
let _7: usize;
2023
scope 4 {
2124
debug z1 => _7;
25+
let _9: usize;
26+
scope 5 {
27+
debug eA0 => _9;
28+
let _11: usize;
29+
scope 6 {
30+
debug eA1 => _11;
31+
let _13: usize;
32+
scope 7 {
33+
debug eC => _13;
34+
}
35+
}
36+
}
2237
}
2338
}
2439
}
@@ -27,7 +42,7 @@
2742
bb0: {
2843
StorageLive(_1);
2944
StorageLive(_2);
30-
- _2 = OffsetOf(Alpha, [0]);
45+
- _2 = OffsetOf(Alpha, [(0, 0)]);
3146
- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable];
3247
+ _2 = const 4_usize;
3348
+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind unreachable];
@@ -37,7 +52,7 @@
3752
StorageDead(_2);
3853
StorageLive(_3);
3954
StorageLive(_4);
40-
- _4 = OffsetOf(Alpha, [1]);
55+
- _4 = OffsetOf(Alpha, [(0, 1)]);
4156
- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable];
4257
+ _4 = const 0_usize;
4358
+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind unreachable];
@@ -47,7 +62,7 @@
4762
StorageDead(_4);
4863
StorageLive(_5);
4964
StorageLive(_6);
50-
- _6 = OffsetOf(Alpha, [2, 0]);
65+
- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]);
5166
- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable];
5267
+ _6 = const 2_usize;
5368
+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind unreachable];
@@ -57,15 +72,48 @@
5772
StorageDead(_6);
5873
StorageLive(_7);
5974
StorageLive(_8);
60-
- _8 = OffsetOf(Alpha, [2, 1]);
75+
- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]);
6176
- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable];
6277
+ _8 = const 3_usize;
6378
+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind unreachable];
6479
}
6580

6681
bb4: {
6782
StorageDead(_8);
83+
StorageLive(_9);
84+
StorageLive(_10);
85+
- _10 = OffsetOf(Epsilon, [(0, 0)]);
86+
- _9 = must_use::<usize>(move _10) -> [return: bb5, unwind unreachable];
87+
+ _10 = const 1_usize;
88+
+ _9 = must_use::<usize>(const 1_usize) -> [return: bb5, unwind unreachable];
89+
}
90+
91+
bb5: {
92+
StorageDead(_10);
93+
StorageLive(_11);
94+
StorageLive(_12);
95+
- _12 = OffsetOf(Epsilon, [(0, 1)]);
96+
- _11 = must_use::<usize>(move _12) -> [return: bb6, unwind unreachable];
97+
+ _12 = const 2_usize;
98+
+ _11 = must_use::<usize>(const 2_usize) -> [return: bb6, unwind unreachable];
99+
}
100+
101+
bb6: {
102+
StorageDead(_12);
103+
StorageLive(_13);
104+
StorageLive(_14);
105+
- _14 = OffsetOf(Epsilon, [(2, 0)]);
106+
- _13 = must_use::<usize>(move _14) -> [return: bb7, unwind unreachable];
107+
+ _14 = const 4_usize;
108+
+ _13 = must_use::<usize>(const 4_usize) -> [return: bb7, unwind unreachable];
109+
}
110+
111+
bb7: {
112+
StorageDead(_14);
68113
_0 = const ();
114+
StorageDead(_13);
115+
StorageDead(_11);
116+
StorageDead(_9);
69117
StorageDead(_7);
70118
StorageDead(_5);
71119
StorageDead(_3);

‎tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
let mut _4: usize;
99
let mut _6: usize;
1010
let mut _8: usize;
11+
let mut _10: usize;
12+
let mut _12: usize;
13+
let mut _14: usize;
1114
scope 1 {
1215
debug x => _1;
1316
let _3: usize;
@@ -19,6 +22,18 @@
1922
let _7: usize;
2023
scope 4 {
2124
debug z1 => _7;
25+
let _9: usize;
26+
scope 5 {
27+
debug eA0 => _9;
28+
let _11: usize;
29+
scope 6 {
30+
debug eA1 => _11;
31+
let _13: usize;
32+
scope 7 {
33+
debug eC => _13;
34+
}
35+
}
36+
}
2237
}
2338
}
2439
}
@@ -27,7 +42,7 @@
2742
bb0: {
2843
StorageLive(_1);
2944
StorageLive(_2);
30-
- _2 = OffsetOf(Alpha, [0]);
45+
- _2 = OffsetOf(Alpha, [(0, 0)]);
3146
- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue];
3247
+ _2 = const 4_usize;
3348
+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind continue];
@@ -37,7 +52,7 @@
3752
StorageDead(_2);
3853
StorageLive(_3);
3954
StorageLive(_4);
40-
- _4 = OffsetOf(Alpha, [1]);
55+
- _4 = OffsetOf(Alpha, [(0, 1)]);
4156
- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue];
4257
+ _4 = const 0_usize;
4358
+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind continue];
@@ -47,7 +62,7 @@
4762
StorageDead(_4);
4863
StorageLive(_5);
4964
StorageLive(_6);
50-
- _6 = OffsetOf(Alpha, [2, 0]);
65+
- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]);
5166
- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue];
5267
+ _6 = const 2_usize;
5368
+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind continue];
@@ -57,15 +72,48 @@
5772
StorageDead(_6);
5873
StorageLive(_7);
5974
StorageLive(_8);
60-
- _8 = OffsetOf(Alpha, [2, 1]);
75+
- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]);
6176
- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue];
6277
+ _8 = const 3_usize;
6378
+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind continue];
6479
}
6580

6681
bb4: {
6782
StorageDead(_8);
83+
StorageLive(_9);
84+
StorageLive(_10);
85+
- _10 = OffsetOf(Epsilon, [(0, 0)]);
86+
- _9 = must_use::<usize>(move _10) -> [return: bb5, unwind continue];
87+
+ _10 = const 1_usize;
88+
+ _9 = must_use::<usize>(const 1_usize) -> [return: bb5, unwind continue];
89+
}
90+
91+
bb5: {
92+
StorageDead(_10);
93+
StorageLive(_11);
94+
StorageLive(_12);
95+
- _12 = OffsetOf(Epsilon, [(0, 1)]);
96+
- _11 = must_use::<usize>(move _12) -> [return: bb6, unwind continue];
97+
+ _12 = const 2_usize;
98+
+ _11 = must_use::<usize>(const 2_usize) -> [return: bb6, unwind continue];
99+
}
100+
101+
bb6: {
102+
StorageDead(_12);
103+
StorageLive(_13);
104+
StorageLive(_14);
105+
- _14 = OffsetOf(Epsilon, [(2, 0)]);
106+
- _13 = must_use::<usize>(move _14) -> [return: bb7, unwind continue];
107+
+ _14 = const 4_usize;
108+
+ _13 = must_use::<usize>(const 4_usize) -> [return: bb7, unwind continue];
109+
}
110+
111+
bb7: {
112+
StorageDead(_14);
68113
_0 = const ();
114+
StorageDead(_13);
115+
StorageDead(_11);
116+
StorageDead(_9);
69117
StorageDead(_7);
70118
StorageDead(_5);
71119
StorageDead(_3);

‎tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-abort.diff

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
let mut _4: usize;
99
let mut _6: usize;
1010
let mut _8: usize;
11+
let mut _10: usize;
12+
let mut _12: usize;
13+
let mut _14: usize;
1114
scope 1 {
1215
debug gx => _1;
1316
let _3: usize;
@@ -19,6 +22,18 @@
1922
let _7: usize;
2023
scope 4 {
2124
debug dy => _7;
25+
let _9: usize;
26+
scope 5 {
27+
debug zA0 => _9;
28+
let _11: usize;
29+
scope 6 {
30+
debug zA1 => _11;
31+
let _13: usize;
32+
scope 7 {
33+
debug zB => _13;
34+
}
35+
}
36+
}
2237
}
2338
}
2439
}
@@ -27,37 +42,64 @@
2742
bb0: {
2843
StorageLive(_1);
2944
StorageLive(_2);
30-
_2 = OffsetOf(Gamma<T>, [0]);
45+
_2 = OffsetOf(Gamma<T>, [(0, 0)]);
3146
_1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable];
3247
}
3348

3449
bb1: {
3550
StorageDead(_2);
3651
StorageLive(_3);
3752
StorageLive(_4);
38-
_4 = OffsetOf(Gamma<T>, [1]);
53+
_4 = OffsetOf(Gamma<T>, [(0, 1)]);
3954
_3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable];
4055
}
4156

4257
bb2: {
4358
StorageDead(_4);
4459
StorageLive(_5);
4560
StorageLive(_6);
46-
_6 = OffsetOf(Delta<T>, [1]);
61+
_6 = OffsetOf(Delta<T>, [(0, 1)]);
4762
_5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable];
4863
}
4964

5065
bb3: {
5166
StorageDead(_6);
5267
StorageLive(_7);
5368
StorageLive(_8);
54-
_8 = OffsetOf(Delta<T>, [2]);
69+
_8 = OffsetOf(Delta<T>, [(0, 2)]);
5570
_7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable];
5671
}
5772

5873
bb4: {
5974
StorageDead(_8);
75+
StorageLive(_9);
76+
StorageLive(_10);
77+
_10 = OffsetOf(Zeta<T>, [(0, 0)]);
78+
_9 = must_use::<usize>(move _10) -> [return: bb5, unwind unreachable];
79+
}
80+
81+
bb5: {
82+
StorageDead(_10);
83+
StorageLive(_11);
84+
StorageLive(_12);
85+
_12 = OffsetOf(Zeta<T>, [(0, 1)]);
86+
_11 = must_use::<usize>(move _12) -> [return: bb6, unwind unreachable];
87+
}
88+
89+
bb6: {
90+
StorageDead(_12);
91+
StorageLive(_13);
92+
StorageLive(_14);
93+
_14 = OffsetOf(Zeta<T>, [(1, 0)]);
94+
_13 = must_use::<usize>(move _14) -> [return: bb7, unwind unreachable];
95+
}
96+
97+
bb7: {
98+
StorageDead(_14);
6099
_0 = const ();
100+
StorageDead(_13);
101+
StorageDead(_11);
102+
StorageDead(_9);
61103
StorageDead(_7);
62104
StorageDead(_5);
63105
StorageDead(_3);

‎tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
let mut _4: usize;
99
let mut _6: usize;
1010
let mut _8: usize;
11+
let mut _10: usize;
12+
let mut _12: usize;
13+
let mut _14: usize;
1114
scope 1 {
1215
debug gx => _1;
1316
let _3: usize;
@@ -19,6 +22,18 @@
1922
let _7: usize;
2023
scope 4 {
2124
debug dy => _7;
25+
let _9: usize;
26+
scope 5 {
27+
debug zA0 => _9;
28+
let _11: usize;
29+
scope 6 {
30+
debug zA1 => _11;
31+
let _13: usize;
32+
scope 7 {
33+
debug zB => _13;
34+
}
35+
}
36+
}
2237
}
2338
}
2439
}
@@ -27,37 +42,64 @@
2742
bb0: {
2843
StorageLive(_1);
2944
StorageLive(_2);
30-
_2 = OffsetOf(Gamma<T>, [0]);
45+
_2 = OffsetOf(Gamma<T>, [(0, 0)]);
3146
_1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue];
3247
}
3348

3449
bb1: {
3550
StorageDead(_2);
3651
StorageLive(_3);
3752
StorageLive(_4);
38-
_4 = OffsetOf(Gamma<T>, [1]);
53+
_4 = OffsetOf(Gamma<T>, [(0, 1)]);
3954
_3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue];
4055
}
4156

4257
bb2: {
4358
StorageDead(_4);
4459
StorageLive(_5);
4560
StorageLive(_6);
46-
_6 = OffsetOf(Delta<T>, [1]);
61+
_6 = OffsetOf(Delta<T>, [(0, 1)]);
4762
_5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue];
4863
}
4964

5065
bb3: {
5166
StorageDead(_6);
5267
StorageLive(_7);
5368
StorageLive(_8);
54-
_8 = OffsetOf(Delta<T>, [2]);
69+
_8 = OffsetOf(Delta<T>, [(0, 2)]);
5570
_7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue];
5671
}
5772

5873
bb4: {
5974
StorageDead(_8);
75+
StorageLive(_9);
76+
StorageLive(_10);
77+
_10 = OffsetOf(Zeta<T>, [(0, 0)]);
78+
_9 = must_use::<usize>(move _10) -> [return: bb5, unwind continue];
79+
}
80+
81+
bb5: {
82+
StorageDead(_10);
83+
StorageLive(_11);
84+
StorageLive(_12);
85+
_12 = OffsetOf(Zeta<T>, [(0, 1)]);
86+
_11 = must_use::<usize>(move _12) -> [return: bb6, unwind continue];
87+
}
88+
89+
bb6: {
90+
StorageDead(_12);
91+
StorageLive(_13);
92+
StorageLive(_14);
93+
_14 = OffsetOf(Zeta<T>, [(1, 0)]);
94+
_13 = must_use::<usize>(move _14) -> [return: bb7, unwind continue];
95+
}
96+
97+
bb7: {
98+
StorageDead(_14);
6099
_0 = const ();
100+
StorageDead(_13);
101+
StorageDead(_11);
102+
StorageDead(_9);
61103
StorageDead(_7);
62104
StorageDead(_5);
63105
StorageDead(_3);

‎tests/mir-opt/const_prop/offset_of.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,26 @@ struct Delta<T> {
2828
y: u16,
2929
}
3030

31+
enum Epsilon {
32+
A(u8, u16),
33+
B,
34+
C { c: u32 }
35+
}
36+
37+
enum Zeta<T> {
38+
A(T, bool),
39+
B(char),
40+
}
41+
3142
// EMIT_MIR offset_of.concrete.ConstProp.diff
3243
fn concrete() {
3344
let x = offset_of!(Alpha, x);
3445
let y = offset_of!(Alpha, y);
3546
let z0 = offset_of!(Alpha, z.0);
3647
let z1 = offset_of!(Alpha, z.1);
48+
let eA0 = offset_of!(Epsilon, A.0);
49+
let eA1 = offset_of!(Epsilon, A.1);
50+
let eC = offset_of!(Epsilon, C.c);
3751
}
3852

3953
// EMIT_MIR offset_of.generic.ConstProp.diff
@@ -42,6 +56,9 @@ fn generic<T>() {
4256
let gy = offset_of!(Gamma<T>, y);
4357
let dx = offset_of!(Delta<T>, x);
4458
let dy = offset_of!(Delta<T>, y);
59+
let zA0 = offset_of!(Zeta<T>, A.0);
60+
let zA1 = offset_of!(Zeta<T>, A.1);
61+
let zB = offset_of!(Zeta<T>, B.0);
4562
}
4663

4764
fn main() {

‎tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
bb0: {
2828
StorageLive(_1);
2929
StorageLive(_2);
30-
- _2 = OffsetOf(Alpha, [0]);
30+
- _2 = OffsetOf(Alpha, [(0, 0)]);
3131
- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable];
3232
+ _2 = const 4_usize;
3333
+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind unreachable];
@@ -37,7 +37,7 @@
3737
StorageDead(_2);
3838
StorageLive(_3);
3939
StorageLive(_4);
40-
- _4 = OffsetOf(Alpha, [1]);
40+
- _4 = OffsetOf(Alpha, [(0, 1)]);
4141
- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable];
4242
+ _4 = const 0_usize;
4343
+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind unreachable];
@@ -47,7 +47,7 @@
4747
StorageDead(_4);
4848
StorageLive(_5);
4949
StorageLive(_6);
50-
- _6 = OffsetOf(Alpha, [2, 0]);
50+
- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]);
5151
- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable];
5252
+ _6 = const 2_usize;
5353
+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind unreachable];
@@ -57,7 +57,7 @@
5757
StorageDead(_6);
5858
StorageLive(_7);
5959
StorageLive(_8);
60-
- _8 = OffsetOf(Alpha, [2, 1]);
60+
- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]);
6161
- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable];
6262
+ _8 = const 3_usize;
6363
+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind unreachable];

‎tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
bb0: {
2828
StorageLive(_1);
2929
StorageLive(_2);
30-
- _2 = OffsetOf(Alpha, [0]);
30+
- _2 = OffsetOf(Alpha, [(0, 0)]);
3131
- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue];
3232
+ _2 = const 4_usize;
3333
+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind continue];
@@ -37,7 +37,7 @@
3737
StorageDead(_2);
3838
StorageLive(_3);
3939
StorageLive(_4);
40-
- _4 = OffsetOf(Alpha, [1]);
40+
- _4 = OffsetOf(Alpha, [(0, 1)]);
4141
- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue];
4242
+ _4 = const 0_usize;
4343
+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind continue];
@@ -47,7 +47,7 @@
4747
StorageDead(_4);
4848
StorageLive(_5);
4949
StorageLive(_6);
50-
- _6 = OffsetOf(Alpha, [2, 0]);
50+
- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]);
5151
- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue];
5252
+ _6 = const 2_usize;
5353
+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind continue];
@@ -57,7 +57,7 @@
5757
StorageDead(_6);
5858
StorageLive(_7);
5959
StorageLive(_8);
60-
- _8 = OffsetOf(Alpha, [2, 1]);
60+
- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]);
6161
- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue];
6262
+ _8 = const 3_usize;
6363
+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind continue];

‎tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,23 @@
2727
bb0: {
2828
StorageLive(_1);
2929
StorageLive(_2);
30-
_2 = OffsetOf(Gamma<T>, [0]);
30+
_2 = OffsetOf(Gamma<T>, [(0, 0)]);
3131
_1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable];
3232
}
3333

3434
bb1: {
3535
StorageDead(_2);
3636
StorageLive(_3);
3737
StorageLive(_4);
38-
_4 = OffsetOf(Gamma<T>, [1]);
38+
_4 = OffsetOf(Gamma<T>, [(0, 1)]);
3939
_3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable];
4040
}
4141

4242
bb2: {
4343
StorageDead(_4);
4444
StorageLive(_5);
4545
StorageLive(_6);
46-
- _6 = OffsetOf(Delta<T>, [1]);
46+
- _6 = OffsetOf(Delta<T>, [(0, 1)]);
4747
- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable];
4848
+ _6 = const 0_usize;
4949
+ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind unreachable];
@@ -53,7 +53,7 @@
5353
StorageDead(_6);
5454
StorageLive(_7);
5555
StorageLive(_8);
56-
- _8 = OffsetOf(Delta<T>, [2]);
56+
- _8 = OffsetOf(Delta<T>, [(0, 2)]);
5757
- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable];
5858
+ _8 = const 2_usize;
5959
+ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind unreachable];

‎tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,23 @@
2727
bb0: {
2828
StorageLive(_1);
2929
StorageLive(_2);
30-
_2 = OffsetOf(Gamma<T>, [0]);
30+
_2 = OffsetOf(Gamma<T>, [(0, 0)]);
3131
_1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue];
3232
}
3333

3434
bb1: {
3535
StorageDead(_2);
3636
StorageLive(_3);
3737
StorageLive(_4);
38-
_4 = OffsetOf(Gamma<T>, [1]);
38+
_4 = OffsetOf(Gamma<T>, [(0, 1)]);
3939
_3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue];
4040
}
4141

4242
bb2: {
4343
StorageDead(_4);
4444
StorageLive(_5);
4545
StorageLive(_6);
46-
- _6 = OffsetOf(Delta<T>, [1]);
46+
- _6 = OffsetOf(Delta<T>, [(0, 1)]);
4747
- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue];
4848
+ _6 = const 0_usize;
4949
+ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind continue];
@@ -53,7 +53,7 @@
5353
StorageDead(_6);
5454
StorageLive(_7);
5555
StorageLive(_8);
56-
- _8 = OffsetOf(Delta<T>, [2]);
56+
- _8 = OffsetOf(Delta<T>, [(0, 2)]);
5757
- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue];
5858
+ _8 = const 2_usize;
5959
+ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind continue];

‎tests/ui/offset-of/offset-of-enum.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,10 @@ enum Alpha {
99

1010
fn main() {
1111
offset_of!(Alpha::One, 0); //~ ERROR expected type, found variant `Alpha::One`
12-
offset_of!(Alpha, Two.0); //~ ERROR no field `Two` on type `Alpha`
12+
offset_of!(Alpha, One); //~ ERROR `One` is an enum variant; expected field at end of `offset_of`
13+
offset_of!(Alpha, Two.0);
14+
offset_of!(Alpha, Two.1); //~ ERROR no field named `1` on enum variant `Alpha::Two`
15+
offset_of!(Alpha, Two.foo); //~ ERROR no field named `foo` on enum variant `Alpha::Two`
16+
offset_of!(Alpha, NonExistent); //~ ERROR no variant named `NonExistent` found for enum `Alpha`
17+
offset_of!(Beta, One); //~ ERROR cannot find type `Beta` in this scope
1318
}

‎tests/ui/offset-of/offset-of-enum.stderr

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,41 @@ LL | offset_of!(Alpha::One, 0);
77
| not a type
88
| help: try using the variant's enum: `Alpha`
99

10-
error[E0609]: no field `Two` on type `Alpha`
10+
error[E0412]: cannot find type `Beta` in this scope
11+
--> $DIR/offset-of-enum.rs:17:16
12+
|
13+
LL | offset_of!(Beta, One);
14+
| ^^^^ not found in this scope
15+
16+
error[E0795]: `One` is an enum variant; expected field at end of `offset_of`
1117
--> $DIR/offset-of-enum.rs:12:23
1218
|
13-
LL | offset_of!(Alpha, Two.0);
14-
| ^^^
19+
LL | offset_of!(Alpha, One);
20+
| ^^^ enum variant
21+
22+
error[E0609]: no field named `1` on enum variant `Alpha::Two`
23+
--> $DIR/offset-of-enum.rs:14:23
24+
|
25+
LL | offset_of!(Alpha, Two.1);
26+
| ^^^ - ...does not have this field
27+
| |
28+
| this enum variant...
29+
30+
error[E0609]: no field named `foo` on enum variant `Alpha::Two`
31+
--> $DIR/offset-of-enum.rs:15:23
32+
|
33+
LL | offset_of!(Alpha, Two.foo);
34+
| ^^^ --- ...does not have this field
35+
| |
36+
| this enum variant...
37+
38+
error[E0599]: no variant named `NonExistent` found for enum `Alpha`
39+
--> $DIR/offset-of-enum.rs:16:23
40+
|
41+
LL | offset_of!(Alpha, NonExistent);
42+
| ^^^^^^^^^^^ variant not found
1543

16-
error: aborting due to 2 previous errors
44+
error: aborting due to 6 previous errors
1745

18-
Some errors have detailed explanations: E0573, E0609.
19-
For more information about an error, try `rustc --explain E0573`.
46+
Some errors have detailed explanations: E0412, E0573, E0599, E0609, E0795.
47+
For more information about an error, try `rustc --explain E0412`.

‎tests/ui/offset-of/offset-of-private.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@ mod m {
88
pub public: u8,
99
private: u8,
1010
}
11+
1112
#[repr(C)]
1213
pub struct FooTuple(pub u8, u8);
14+
1315
#[repr(C)]
1416
struct Bar {
1517
pub public: u8,
1618
private: u8,
1719
}
20+
21+
pub enum Baz {
22+
Var1(Foo),
23+
Var2(u64),
24+
}
1825
}
1926

2027
fn main() {
@@ -25,4 +32,8 @@ fn main() {
2532
offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private
2633
offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private
2734
//~| ERROR field `private` of struct `Bar` is private
35+
36+
offset_of!(m::Baz, Var1.0.public);
37+
offset_of!(m::Baz, Var1.0.private); //~ ERROR field `private` of struct `Foo` is private
38+
offset_of!(m::Baz, Var2.0);
2839
}
Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,52 @@
11
error[E0603]: struct `Bar` is private
2-
--> $DIR/offset-of-private.rs:25:19
2+
--> $DIR/offset-of-private.rs:32:19
33
|
44
LL | offset_of!(m::Bar, public);
55
| ^^^ private struct
66
|
77
note: the struct `Bar` is defined here
8-
--> $DIR/offset-of-private.rs:14:5
8+
--> $DIR/offset-of-private.rs:16:5
99
|
1010
LL | struct Bar {
1111
| ^^^^^^^^^^
1212

1313
error[E0603]: struct `Bar` is private
14-
--> $DIR/offset-of-private.rs:26:19
14+
--> $DIR/offset-of-private.rs:33:19
1515
|
1616
LL | offset_of!(m::Bar, private);
1717
| ^^^ private struct
1818
|
1919
note: the struct `Bar` is defined here
20-
--> $DIR/offset-of-private.rs:14:5
20+
--> $DIR/offset-of-private.rs:16:5
2121
|
2222
LL | struct Bar {
2323
| ^^^^^^^^^^
2424

2525
error[E0616]: field `private` of struct `Foo` is private
26-
--> $DIR/offset-of-private.rs:22:24
26+
--> $DIR/offset-of-private.rs:29:24
2727
|
2828
LL | offset_of!(m::Foo, private);
2929
| ^^^^^^^ private field
3030

3131
error[E0616]: field `1` of struct `FooTuple` is private
32-
--> $DIR/offset-of-private.rs:24:29
32+
--> $DIR/offset-of-private.rs:31:29
3333
|
3434
LL | offset_of!(m::FooTuple, 1);
3535
| ^ private field
3636

3737
error[E0616]: field `private` of struct `Bar` is private
38-
--> $DIR/offset-of-private.rs:26:24
38+
--> $DIR/offset-of-private.rs:33:24
3939
|
4040
LL | offset_of!(m::Bar, private);
4141
| ^^^^^^^ private field
4242

43-
error: aborting due to 5 previous errors
43+
error[E0616]: field `private` of struct `Foo` is private
44+
--> $DIR/offset-of-private.rs:37:31
45+
|
46+
LL | offset_of!(m::Baz, Var1.0.private);
47+
| ^^^^^^^ private field
48+
49+
error: aborting due to 6 previous errors
4450

4551
Some errors have detailed explanations: E0603, E0616.
4652
For more information about an error, try `rustc --explain E0603`.

0 commit comments

Comments
 (0)
Please sign in to comment.