diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 80e7c5bd9edbc..91b1547cb6ea6 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -766,7 +766,7 @@ fn codegen_stmt<'tcx>( NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(fx, fields.iter().map(|f| f.index())).bytes() + layout.offset_of_subfield(fx, fields.iter()).bytes() } }; let val = CValue::by_val( diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f591afaaaf427..b0f757898e326 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -680,7 +680,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { layout.align.abi.bytes() } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(bx.cx(), fields.iter().map(|f| f.index())).bytes() + layout.offset_of_subfield(bx.cx(), fields.iter()).bytes() } }; let val = bx.cx().const_usize(val); diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 8c34d05042b1d..b6993d939c585 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -275,7 +275,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(self, fields.iter().map(|f| f.index())).bytes() + layout.offset_of_subfield(self, fields.iter()).bytes() } }; self.write_scalar(Scalar::from_target_usize(val, self), &dest)?; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b70a342aa15e6..4d71f76366768 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1056,16 +1056,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } - Rvalue::NullaryOp(NullOp::OffsetOf(fields), container) => { + Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => { let fail_out_of_bounds = |this: &mut Self, location, field, ty| { this.fail(location, format!("Out of bounds field {field:?} for {ty:?}")); }; let mut current_ty = *container; - for field in fields.iter() { + for (variant, field) in indices.iter() { match current_ty.kind() { ty::Tuple(fields) => { + if variant != FIRST_VARIANT { + self.fail( + location, + format!("tried to get variant {variant:?} of tuple"), + ); + return; + } let Some(&f_ty) = fields.get(field.as_usize()) else { fail_out_of_bounds(self, location, field, current_ty); return; @@ -1074,15 +1081,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); } ty::Adt(adt_def, args) => { - if adt_def.is_enum() { - self.fail( - location, - format!("Cannot get field offset from enum {current_ty:?}"), - ); - return; - } - - let Some(field) = adt_def.non_enum_variant().fields.get(field) else { + let Some(field) = adt_def.variant(variant).fields.get(field) else { fail_out_of_bounds(self, location, field, current_ty); return; }; @@ -1093,7 +1092,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { _ => { self.fail( location, - format!("Cannot get field offset from non-adt type {current_ty:?}"), + format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"), ); return; } diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 89c44c6ec8a90..6680e8875c3e3 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -514,6 +514,7 @@ E0791: include_str!("./error_codes/E0791.md"), E0792: include_str!("./error_codes/E0792.md"), E0793: include_str!("./error_codes/E0793.md"), E0794: include_str!("./error_codes/E0794.md"), +E0795: include_str!("./error_codes/E0795.md"), } // Undocumented removed error codes. Note that many removed error codes are kept in the list above diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md new file mode 100644 index 0000000000000..8b4b2dc87fd71 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -0,0 +1,28 @@ +Invalid argument for the `offset_of!` macro. + +Erroneous code example: + +```compile_fail,E0795 +#![feature(offset_of)] + +let x = std::mem::offset_of!(Option, Some); +``` + +The `offset_of!` macro gives the offset of a field within a type. It can +navigate through enum variants, but the final component of its second argument +must be a field and not a variant. + +The offset of the contained `u8` in the `Option` can be found by specifying +the field name `0`: + +``` +#![feature(offset_of)] + +let x: usize = std::mem::offset_of!(Option, Some.0); +``` + +The discriminant of an enumeration may be read with `core::mem::discriminant`, +but this is not always a value physically present within the enum. + +Further information about enum layout may be found at +https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b1d6e4f0523b6..bdac886bf9e73 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -54,7 +54,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_target::abi::FieldIdx; +use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use rustc_target::spec::abi::Abi::RustIntrinsic; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -3107,12 +3107,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut field_indices = Vec::with_capacity(fields.len()); let mut current_container = container; + let mut fields = fields.into_iter(); - for &field in fields { + while let Some(&field) = fields.next() { let container = self.structurally_resolve_type(expr.span, current_container); match container.kind() { - ty::Adt(container_def, args) if !container_def.is_enum() => { + ty::Adt(container_def, args) if container_def.is_enum() => { + let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id); + let (ident, _def_scope) = + self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); + + let Some((index, variant)) = container_def.variants() + .iter_enumerated() + .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else { + let mut err = type_error_struct!( + self.tcx().sess, + ident.span, + container, + E0599, + "no variant named `{ident}` found for enum `{container}`", + ); + err.span_label(field.span, "variant not found"); + err.emit(); + break; + }; + let Some(&subfield) = fields.next() else { + let mut err = type_error_struct!( + self.tcx().sess, + ident.span, + container, + E0795, + "`{ident}` is an enum variant; expected field at end of `offset_of`", + ); + err.span_label(field.span, "enum variant"); + err.emit(); + break; + }; + let (subident, sub_def_scope) = + self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block); + + let Some((subindex, field)) = variant.fields + .iter_enumerated() + .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) else { + let mut err = type_error_struct!( + self.tcx().sess, + ident.span, + container, + E0609, + "no field named `{subfield}` on enum variant `{container}::{ident}`", + ); + err.span_label(field.span, "this enum variant..."); + err.span_label(subident.span, "...does not have this field"); + err.emit(); + break; + }; + + let field_ty = self.field_ty(expr.span, field, args); + + // FIXME: DSTs with static alignment should be allowed + self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation); + + if field.vis.is_accessible_from(sub_def_scope, self.tcx) { + self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); + } else { + self.private_field_err(ident, container_def.did()).emit(); + } + + // Save the index of all fields regardless of their visibility in case + // of error recovery. + field_indices.push((index, subindex)); + current_container = field_ty; + + continue; + } + ty::Adt(container_def, args) => { let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id); let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); @@ -3135,7 +3204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Save the index of all fields regardless of their visibility in case // of error recovery. - field_indices.push(index); + field_indices.push((FIRST_VARIANT, index)); current_container = field_ty; continue; @@ -3149,7 +3218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized(ty, expr.span, traits::MiscObligation); } if let Some(&field_ty) = tys.get(index) { - field_indices.push(index.into()); + field_indices.push((FIRST_VARIANT, index.into())); current_container = field_ty; continue; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index b89c7bc512e1e..b6543affc6dbe 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1354,7 +1354,7 @@ pub enum NullOp<'tcx> { /// Returns the minimum alignment of a type AlignOf, /// Returns the offset of a field - OffsetOf(&'tcx List), + OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 9457b62f22c1f..3086082fe8d57 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -492,7 +492,7 @@ pub enum ExprKind<'tcx> { /// Field offset (`offset_of!`) OffsetOf { container: Ty<'tcx>, - fields: &'tcx List, + fields: &'tcx List<(VariantIdx, FieldIdx)>, }, /// An expression taking a reference to a thread local. ThreadLocalRef(DefId), diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index d52a717b6b09b..8b67e39667b8d 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -19,7 +19,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::TyCtxt; use rustc_serialize::{Decodable, Encodable}; use rustc_span::Span; -use rustc_target::abi::FieldIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; pub use rustc_type_ir::{TyDecoder, TyEncoder}; use std::hash::Hash; use std::intrinsics; @@ -414,6 +414,17 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List>> RefDecodable<'tcx, D> + for ty::List<(VariantIdx, FieldIdx)> +{ + fn decode(decoder: &mut D) -> &'tcx Self { + let len = decoder.read_usize(); + decoder.interner().mk_offset_of_from_iter( + (0..len).map::<(VariantIdx, FieldIdx), _>(|_| Decodable::decode(decoder)), + ) + } +} + impl_decodable_via_ref! { &'tcx ty::TypeckResults<'tcx>, &'tcx ty::List>, @@ -426,6 +437,7 @@ impl_decodable_via_ref! { &'tcx ty::List, &'tcx ty::List>, &'tcx ty::List, + &'tcx ty::List<(VariantIdx, FieldIdx)>, } #[macro_export] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0b3b6700cec1b..68812bba42fdd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -163,6 +163,7 @@ pub struct CtxtInterners<'tcx> { predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>, fields: InternedSet<'tcx, List>, local_def_ids: InternedSet<'tcx, List>, + offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>, } impl<'tcx> CtxtInterners<'tcx> { @@ -189,6 +190,7 @@ impl<'tcx> CtxtInterners<'tcx> { predefined_opaques_in_body: Default::default(), fields: Default::default(), local_def_ids: Default::default(), + offset_of: Default::default(), } } @@ -1587,6 +1589,7 @@ slice_interners!( bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind), fields: pub mk_fields(FieldIdx), local_def_ids: intern_local_def_ids(LocalDefId), + offset_of: pub mk_offset_of((VariantIdx, FieldIdx)), ); impl<'tcx> TyCtxt<'tcx> { @@ -1914,6 +1917,14 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_fields(xs)) } + pub fn mk_offset_of_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: CollectAndApply<(VariantIdx, FieldIdx), &'tcx List<(VariantIdx, FieldIdx)>>, + { + T::collect_and_apply(iter, |xs| self.mk_offset_of(xs)) + } + pub fn mk_args_trait( self, self_ty: Ty<'tcx>, diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 58ad1eb900fd5..e9240d1b268e6 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -24,7 +24,7 @@ use rustc_macros::HashStable; use rustc_middle::mir::FakeReadCause; use rustc_session::Session; use rustc_span::Span; -use rustc_target::abi::FieldIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use std::{collections::hash_map::Entry, hash::Hash, iter}; use super::RvalueScopes; @@ -205,7 +205,7 @@ pub struct TypeckResults<'tcx> { pub closure_size_eval: LocalDefIdMap>, /// Container types and field indices of `offset_of!` expressions - offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec)>, + offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>, } impl<'tcx> TypeckResults<'tcx> { @@ -464,11 +464,15 @@ impl<'tcx> TypeckResults<'tcx> { &self.coercion_casts } - pub fn offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec)> { + pub fn offset_of_data( + &self, + ) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data } } - pub fn offset_of_data_mut(&mut self) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec)> { + pub fn offset_of_data_mut( + &mut self, + ) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data } } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 6c3564a20f6bf..dfd39b512e241 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -670,7 +670,7 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::OffsetOf(_, _) => { let data = self.typeck_results.offset_of_data(); let &(container, ref indices) = data.get(expr.hir_id).unwrap(); - let fields = tcx.mk_fields_from_iter(indices.iter().copied()); + let fields = tcx.mk_offset_of_from_iter(indices.iter().copied()); ExprKind::OffsetOf { container, fields } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index fd067cb234bdb..81d2bba989a7f 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -286,9 +286,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { let val = match null_op { NullOp::SizeOf if layout.is_sized() => layout.size.bytes(), NullOp::AlignOf if layout.is_sized() => layout.align.abi.bytes(), - NullOp::OffsetOf(fields) => layout - .offset_of_subfield(&self.ecx, fields.iter().map(|f| f.index())) - .bytes(), + NullOp::OffsetOf(fields) => { + layout.offset_of_subfield(&self.ecx, fields.iter()).bytes() + } _ => return ValueOrPlace::Value(FlatSet::Top), }; FlatSet::Elem(Scalar::from_target_usize(val, &self.tcx)) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index de0dc25808b30..dce298e92e166 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -467,9 +467,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let val = match null_op { NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), - NullOp::OffsetOf(fields) => layout - .offset_of_subfield(&self.ecx, fields.iter().map(|f| f.index())) - .bytes(), + NullOp::OffsetOf(fields) => { + layout.offset_of_subfield(&self.ecx, fields.iter()).bytes() + } }; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let imm = ImmTy::try_from_uint(val, usize_layout)?; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 87d4850b475bd..2e8c58b0241f9 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -257,10 +257,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { let mut current_ty = container; - for &index in indices { + for &(variant, field) in indices { match current_ty.kind() { ty::Adt(def, subst) => { - let field = &def.non_enum_variant().fields[index]; + let field = &def.variant(variant).fields[field]; self.insert_def_id(field.did); let field_ty = field.ty(self.tcx, subst); @@ -271,7 +271,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { // but we may need to mark subfields ty::Tuple(tys) => { current_ty = - self.tcx.normalize_erasing_regions(param_env, tys[index.as_usize()]); + self.tcx.normalize_erasing_regions(param_env, tys[field.as_usize()]); } _ => span_bug!(expr.span, "named field access on non-ADT"), } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index b619ce6e35f99..25bd82bf1ef52 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -649,6 +649,13 @@ impl<'tcx> Stable<'tcx> for FieldIdx { } } +impl<'tcx> Stable<'tcx> for (rustc_target::abi::VariantIdx, FieldIdx) { + type T = (usize, usize); + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + (self.0.as_usize(), self.1.as_usize()) + } +} + impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { type T = stable_mir::mir::Operand; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index f6f8b53d130b5..b00567e87c656 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -250,14 +250,17 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty::is_transparent(self) } - pub fn offset_of_subfield(self, cx: &C, indices: impl Iterator) -> Size + pub fn offset_of_subfield(self, cx: &C, indices: I) -> Size where Ty: TyAbiInterface<'a, C>, + I: Iterator, { let mut layout = self; let mut offset = Size::ZERO; - for index in indices { + for (variant, field) in indices { + layout = layout.for_variant(cx, variant); + let index = field.index(); offset += layout.fields.offset(index); layout = layout.field(cx, index); assert!( diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 804f5e3d9d0c4..4818bceadeffc 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -516,7 +516,7 @@ pub enum NullOp { /// Returns the minimum alignment of a type. AlignOf, /// Returns the offset of a field. - OffsetOf(Vec), + OffsetOf(Vec<(VariantIdx, FieldIdx)>), } impl Operand { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index df79c3a338a15..8792134cdc862 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1292,11 +1292,15 @@ impl SizedTypeProperties for T {} /// Expands to the offset in bytes of a field from the beginning of the given type. /// -/// Only structs, unions and tuples are supported. +/// Structs, enums, unions and tuples are supported. /// /// Nested field accesses may be used, but not array indexes like in `C`'s `offsetof`. /// -/// Note that the output of this macro is not stable, except for `#[repr(C)]` types. +/// Enum variants may be traversed as if they were fields. Variants themselves do +/// not have an offset. +/// +/// Note that type layout is, in general, [subject to change and +/// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). /// /// # Examples /// @@ -1324,6 +1328,9 @@ impl SizedTypeProperties for T {} /// struct NestedB(u8); /// /// assert_eq!(mem::offset_of!(NestedA, b.0), 0); +/// +/// # #[cfg(not(bootstrap))] +/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` #[unstable(feature = "offset_of", issue = "106655")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-abort.diff index c73d217aeec4e..711db3d21dd72 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-abort.diff @@ -8,6 +8,9 @@ let mut _4: usize; let mut _6: usize; let mut _8: usize; + let mut _10: usize; + let mut _12: usize; + let mut _14: usize; scope 1 { debug x => _1; let _3: usize; @@ -19,6 +22,18 @@ let _7: usize; scope 4 { debug z1 => _7; + let _9: usize; + scope 5 { + debug eA0 => _9; + let _11: usize; + scope 6 { + debug eA1 => _11; + let _13: usize; + scope 7 { + debug eC => _13; + } + } + } } } } @@ -27,7 +42,7 @@ bb0: { StorageLive(_1); StorageLive(_2); -- _2 = OffsetOf(Alpha, [0]); +- _2 = OffsetOf(Alpha, [(0, 0)]); - _1 = must_use::(move _2) -> [return: bb1, unwind unreachable]; + _2 = const 4_usize; + _1 = must_use::(const 4_usize) -> [return: bb1, unwind unreachable]; @@ -37,7 +52,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); -- _4 = OffsetOf(Alpha, [1]); +- _4 = OffsetOf(Alpha, [(0, 1)]); - _3 = must_use::(move _4) -> [return: bb2, unwind unreachable]; + _4 = const 0_usize; + _3 = must_use::(const 0_usize) -> [return: bb2, unwind unreachable]; @@ -47,7 +62,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); -- _6 = OffsetOf(Alpha, [2, 0]); +- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); - _5 = must_use::(move _6) -> [return: bb3, unwind unreachable]; + _6 = const 2_usize; + _5 = must_use::(const 2_usize) -> [return: bb3, unwind unreachable]; @@ -57,7 +72,7 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); -- _8 = OffsetOf(Alpha, [2, 1]); +- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); - _7 = must_use::(move _8) -> [return: bb4, unwind unreachable]; + _8 = const 3_usize; + _7 = must_use::(const 3_usize) -> [return: bb4, unwind unreachable]; @@ -65,7 +80,40 @@ bb4: { StorageDead(_8); + StorageLive(_9); + StorageLive(_10); +- _10 = OffsetOf(Epsilon, [(0, 0)]); +- _9 = must_use::(move _10) -> [return: bb5, unwind unreachable]; ++ _10 = const 1_usize; ++ _9 = must_use::(const 1_usize) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_10); + StorageLive(_11); + StorageLive(_12); +- _12 = OffsetOf(Epsilon, [(0, 1)]); +- _11 = must_use::(move _12) -> [return: bb6, unwind unreachable]; ++ _12 = const 2_usize; ++ _11 = must_use::(const 2_usize) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_12); + StorageLive(_13); + StorageLive(_14); +- _14 = OffsetOf(Epsilon, [(2, 0)]); +- _13 = must_use::(move _14) -> [return: bb7, unwind unreachable]; ++ _14 = const 4_usize; ++ _13 = must_use::(const 4_usize) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_14); _0 = const (); + StorageDead(_13); + StorageDead(_11); + StorageDead(_9); StorageDead(_7); StorageDead(_5); StorageDead(_3); diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff index 913ffca4ae904..49458145415c7 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff @@ -8,6 +8,9 @@ let mut _4: usize; let mut _6: usize; let mut _8: usize; + let mut _10: usize; + let mut _12: usize; + let mut _14: usize; scope 1 { debug x => _1; let _3: usize; @@ -19,6 +22,18 @@ let _7: usize; scope 4 { debug z1 => _7; + let _9: usize; + scope 5 { + debug eA0 => _9; + let _11: usize; + scope 6 { + debug eA1 => _11; + let _13: usize; + scope 7 { + debug eC => _13; + } + } + } } } } @@ -27,7 +42,7 @@ bb0: { StorageLive(_1); StorageLive(_2); -- _2 = OffsetOf(Alpha, [0]); +- _2 = OffsetOf(Alpha, [(0, 0)]); - _1 = must_use::(move _2) -> [return: bb1, unwind continue]; + _2 = const 4_usize; + _1 = must_use::(const 4_usize) -> [return: bb1, unwind continue]; @@ -37,7 +52,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); -- _4 = OffsetOf(Alpha, [1]); +- _4 = OffsetOf(Alpha, [(0, 1)]); - _3 = must_use::(move _4) -> [return: bb2, unwind continue]; + _4 = const 0_usize; + _3 = must_use::(const 0_usize) -> [return: bb2, unwind continue]; @@ -47,7 +62,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); -- _6 = OffsetOf(Alpha, [2, 0]); +- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); - _5 = must_use::(move _6) -> [return: bb3, unwind continue]; + _6 = const 2_usize; + _5 = must_use::(const 2_usize) -> [return: bb3, unwind continue]; @@ -57,7 +72,7 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); -- _8 = OffsetOf(Alpha, [2, 1]); +- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); - _7 = must_use::(move _8) -> [return: bb4, unwind continue]; + _8 = const 3_usize; + _7 = must_use::(const 3_usize) -> [return: bb4, unwind continue]; @@ -65,7 +80,40 @@ bb4: { StorageDead(_8); + StorageLive(_9); + StorageLive(_10); +- _10 = OffsetOf(Epsilon, [(0, 0)]); +- _9 = must_use::(move _10) -> [return: bb5, unwind continue]; ++ _10 = const 1_usize; ++ _9 = must_use::(const 1_usize) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_10); + StorageLive(_11); + StorageLive(_12); +- _12 = OffsetOf(Epsilon, [(0, 1)]); +- _11 = must_use::(move _12) -> [return: bb6, unwind continue]; ++ _12 = const 2_usize; ++ _11 = must_use::(const 2_usize) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_12); + StorageLive(_13); + StorageLive(_14); +- _14 = OffsetOf(Epsilon, [(2, 0)]); +- _13 = must_use::(move _14) -> [return: bb7, unwind continue]; ++ _14 = const 4_usize; ++ _13 = must_use::(const 4_usize) -> [return: bb7, unwind continue]; + } + + bb7: { + StorageDead(_14); _0 = const (); + StorageDead(_13); + StorageDead(_11); + StorageDead(_9); StorageDead(_7); StorageDead(_5); StorageDead(_3); diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-abort.diff index 7519331f6d7d4..768970a7250f0 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-abort.diff @@ -8,6 +8,9 @@ let mut _4: usize; let mut _6: usize; let mut _8: usize; + let mut _10: usize; + let mut _12: usize; + let mut _14: usize; scope 1 { debug gx => _1; let _3: usize; @@ -19,6 +22,18 @@ let _7: usize; scope 4 { debug dy => _7; + let _9: usize; + scope 5 { + debug zA0 => _9; + let _11: usize; + scope 6 { + debug zA1 => _11; + let _13: usize; + scope 7 { + debug zB => _13; + } + } + } } } } @@ -27,7 +42,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = OffsetOf(Gamma, [0]); + _2 = OffsetOf(Gamma, [(0, 0)]); _1 = must_use::(move _2) -> [return: bb1, unwind unreachable]; } @@ -35,7 +50,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); - _4 = OffsetOf(Gamma, [1]); + _4 = OffsetOf(Gamma, [(0, 1)]); _3 = must_use::(move _4) -> [return: bb2, unwind unreachable]; } @@ -43,7 +58,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = OffsetOf(Delta, [1]); + _6 = OffsetOf(Delta, [(0, 1)]); _5 = must_use::(move _6) -> [return: bb3, unwind unreachable]; } @@ -51,13 +66,40 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); - _8 = OffsetOf(Delta, [2]); + _8 = OffsetOf(Delta, [(0, 2)]); _7 = must_use::(move _8) -> [return: bb4, unwind unreachable]; } bb4: { StorageDead(_8); + StorageLive(_9); + StorageLive(_10); + _10 = OffsetOf(Zeta, [(0, 0)]); + _9 = must_use::(move _10) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_10); + StorageLive(_11); + StorageLive(_12); + _12 = OffsetOf(Zeta, [(0, 1)]); + _11 = must_use::(move _12) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_12); + StorageLive(_13); + StorageLive(_14); + _14 = OffsetOf(Zeta, [(1, 0)]); + _13 = must_use::(move _14) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_14); _0 = const (); + StorageDead(_13); + StorageDead(_11); + StorageDead(_9); StorageDead(_7); StorageDead(_5); StorageDead(_3); diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff index fd5206e460c6d..04ccd2b36e0d8 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff @@ -8,6 +8,9 @@ let mut _4: usize; let mut _6: usize; let mut _8: usize; + let mut _10: usize; + let mut _12: usize; + let mut _14: usize; scope 1 { debug gx => _1; let _3: usize; @@ -19,6 +22,18 @@ let _7: usize; scope 4 { debug dy => _7; + let _9: usize; + scope 5 { + debug zA0 => _9; + let _11: usize; + scope 6 { + debug zA1 => _11; + let _13: usize; + scope 7 { + debug zB => _13; + } + } + } } } } @@ -27,7 +42,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = OffsetOf(Gamma, [0]); + _2 = OffsetOf(Gamma, [(0, 0)]); _1 = must_use::(move _2) -> [return: bb1, unwind continue]; } @@ -35,7 +50,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); - _4 = OffsetOf(Gamma, [1]); + _4 = OffsetOf(Gamma, [(0, 1)]); _3 = must_use::(move _4) -> [return: bb2, unwind continue]; } @@ -43,7 +58,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = OffsetOf(Delta, [1]); + _6 = OffsetOf(Delta, [(0, 1)]); _5 = must_use::(move _6) -> [return: bb3, unwind continue]; } @@ -51,13 +66,40 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); - _8 = OffsetOf(Delta, [2]); + _8 = OffsetOf(Delta, [(0, 2)]); _7 = must_use::(move _8) -> [return: bb4, unwind continue]; } bb4: { StorageDead(_8); + StorageLive(_9); + StorageLive(_10); + _10 = OffsetOf(Zeta, [(0, 0)]); + _9 = must_use::(move _10) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_10); + StorageLive(_11); + StorageLive(_12); + _12 = OffsetOf(Zeta, [(0, 1)]); + _11 = must_use::(move _12) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_12); + StorageLive(_13); + StorageLive(_14); + _14 = OffsetOf(Zeta, [(1, 0)]); + _13 = must_use::(move _14) -> [return: bb7, unwind continue]; + } + + bb7: { + StorageDead(_14); _0 = const (); + StorageDead(_13); + StorageDead(_11); + StorageDead(_9); StorageDead(_7); StorageDead(_5); StorageDead(_3); diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 21911f8dbb5de..8a5289d589914 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -28,12 +28,26 @@ struct Delta { y: u16, } +enum Epsilon { + A(u8, u16), + B, + C { c: u32 } +} + +enum Zeta { + A(T, bool), + B(char), +} + // EMIT_MIR offset_of.concrete.ConstProp.diff fn concrete() { let x = offset_of!(Alpha, x); let y = offset_of!(Alpha, y); let z0 = offset_of!(Alpha, z.0); let z1 = offset_of!(Alpha, z.1); + let eA0 = offset_of!(Epsilon, A.0); + let eA1 = offset_of!(Epsilon, A.1); + let eC = offset_of!(Epsilon, C.c); } // EMIT_MIR offset_of.generic.ConstProp.diff @@ -42,6 +56,9 @@ fn generic() { let gy = offset_of!(Gamma, y); let dx = offset_of!(Delta, x); let dy = offset_of!(Delta, y); + let zA0 = offset_of!(Zeta, A.0); + let zA1 = offset_of!(Zeta, A.1); + let zB = offset_of!(Zeta, B.0); } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff index c61414b6541a7..f8f8917503370 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff @@ -27,7 +27,7 @@ bb0: { StorageLive(_1); StorageLive(_2); -- _2 = OffsetOf(Alpha, [0]); +- _2 = OffsetOf(Alpha, [(0, 0)]); - _1 = must_use::(move _2) -> [return: bb1, unwind unreachable]; + _2 = const 4_usize; + _1 = must_use::(const 4_usize) -> [return: bb1, unwind unreachable]; @@ -37,7 +37,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); -- _4 = OffsetOf(Alpha, [1]); +- _4 = OffsetOf(Alpha, [(0, 1)]); - _3 = must_use::(move _4) -> [return: bb2, unwind unreachable]; + _4 = const 0_usize; + _3 = must_use::(const 0_usize) -> [return: bb2, unwind unreachable]; @@ -47,7 +47,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); -- _6 = OffsetOf(Alpha, [2, 0]); +- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); - _5 = must_use::(move _6) -> [return: bb3, unwind unreachable]; + _6 = const 2_usize; + _5 = must_use::(const 2_usize) -> [return: bb3, unwind unreachable]; @@ -57,7 +57,7 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); -- _8 = OffsetOf(Alpha, [2, 1]); +- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); - _7 = must_use::(move _8) -> [return: bb4, unwind unreachable]; + _8 = const 3_usize; + _7 = must_use::(const 3_usize) -> [return: bb4, unwind unreachable]; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff index 0c3939a3456ac..d4f8cb66704ae 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff @@ -27,7 +27,7 @@ bb0: { StorageLive(_1); StorageLive(_2); -- _2 = OffsetOf(Alpha, [0]); +- _2 = OffsetOf(Alpha, [(0, 0)]); - _1 = must_use::(move _2) -> [return: bb1, unwind continue]; + _2 = const 4_usize; + _1 = must_use::(const 4_usize) -> [return: bb1, unwind continue]; @@ -37,7 +37,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); -- _4 = OffsetOf(Alpha, [1]); +- _4 = OffsetOf(Alpha, [(0, 1)]); - _3 = must_use::(move _4) -> [return: bb2, unwind continue]; + _4 = const 0_usize; + _3 = must_use::(const 0_usize) -> [return: bb2, unwind continue]; @@ -47,7 +47,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); -- _6 = OffsetOf(Alpha, [2, 0]); +- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); - _5 = must_use::(move _6) -> [return: bb3, unwind continue]; + _6 = const 2_usize; + _5 = must_use::(const 2_usize) -> [return: bb3, unwind continue]; @@ -57,7 +57,7 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); -- _8 = OffsetOf(Alpha, [2, 1]); +- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); - _7 = must_use::(move _8) -> [return: bb4, unwind continue]; + _8 = const 3_usize; + _7 = must_use::(const 3_usize) -> [return: bb4, unwind continue]; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff index d54d46870609d..7f166e4fa356a 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff @@ -27,7 +27,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = OffsetOf(Gamma, [0]); + _2 = OffsetOf(Gamma, [(0, 0)]); _1 = must_use::(move _2) -> [return: bb1, unwind unreachable]; } @@ -35,7 +35,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); - _4 = OffsetOf(Gamma, [1]); + _4 = OffsetOf(Gamma, [(0, 1)]); _3 = must_use::(move _4) -> [return: bb2, unwind unreachable]; } @@ -43,7 +43,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); -- _6 = OffsetOf(Delta, [1]); +- _6 = OffsetOf(Delta, [(0, 1)]); - _5 = must_use::(move _6) -> [return: bb3, unwind unreachable]; + _6 = const 0_usize; + _5 = must_use::(const 0_usize) -> [return: bb3, unwind unreachable]; @@ -53,7 +53,7 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); -- _8 = OffsetOf(Delta, [2]); +- _8 = OffsetOf(Delta, [(0, 2)]); - _7 = must_use::(move _8) -> [return: bb4, unwind unreachable]; + _8 = const 2_usize; + _7 = must_use::(const 2_usize) -> [return: bb4, unwind unreachable]; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff index 6032a2274efe9..38ad6f7980160 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff @@ -27,7 +27,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = OffsetOf(Gamma, [0]); + _2 = OffsetOf(Gamma, [(0, 0)]); _1 = must_use::(move _2) -> [return: bb1, unwind continue]; } @@ -35,7 +35,7 @@ StorageDead(_2); StorageLive(_3); StorageLive(_4); - _4 = OffsetOf(Gamma, [1]); + _4 = OffsetOf(Gamma, [(0, 1)]); _3 = must_use::(move _4) -> [return: bb2, unwind continue]; } @@ -43,7 +43,7 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); -- _6 = OffsetOf(Delta, [1]); +- _6 = OffsetOf(Delta, [(0, 1)]); - _5 = must_use::(move _6) -> [return: bb3, unwind continue]; + _6 = const 0_usize; + _5 = must_use::(const 0_usize) -> [return: bb3, unwind continue]; @@ -53,7 +53,7 @@ StorageDead(_6); StorageLive(_7); StorageLive(_8); -- _8 = OffsetOf(Delta, [2]); +- _8 = OffsetOf(Delta, [(0, 2)]); - _7 = must_use::(move _8) -> [return: bb4, unwind continue]; + _8 = const 2_usize; + _7 = must_use::(const 2_usize) -> [return: bb4, unwind continue]; diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index d73505821ff53..e8b5a08377bdd 100644 --- a/tests/ui/offset-of/offset-of-enum.rs +++ b/tests/ui/offset-of/offset-of-enum.rs @@ -9,5 +9,10 @@ enum Alpha { fn main() { offset_of!(Alpha::One, 0); //~ ERROR expected type, found variant `Alpha::One` - offset_of!(Alpha, Two.0); //~ ERROR no field `Two` on type `Alpha` + offset_of!(Alpha, One); //~ ERROR `One` is an enum variant; expected field at end of `offset_of` + offset_of!(Alpha, Two.0); + offset_of!(Alpha, Two.1); //~ ERROR no field named `1` on enum variant `Alpha::Two` + offset_of!(Alpha, Two.foo); //~ ERROR no field named `foo` on enum variant `Alpha::Two` + offset_of!(Alpha, NonExistent); //~ ERROR no variant named `NonExistent` found for enum `Alpha` + offset_of!(Beta, One); //~ ERROR cannot find type `Beta` in this scope } diff --git a/tests/ui/offset-of/offset-of-enum.stderr b/tests/ui/offset-of/offset-of-enum.stderr index 6958d199fbdb4..7e7ad41f5b6a9 100644 --- a/tests/ui/offset-of/offset-of-enum.stderr +++ b/tests/ui/offset-of/offset-of-enum.stderr @@ -7,13 +7,41 @@ LL | offset_of!(Alpha::One, 0); | not a type | help: try using the variant's enum: `Alpha` -error[E0609]: no field `Two` on type `Alpha` +error[E0412]: cannot find type `Beta` in this scope + --> $DIR/offset-of-enum.rs:17:16 + | +LL | offset_of!(Beta, One); + | ^^^^ not found in this scope + +error[E0795]: `One` is an enum variant; expected field at end of `offset_of` --> $DIR/offset-of-enum.rs:12:23 | -LL | offset_of!(Alpha, Two.0); - | ^^^ +LL | offset_of!(Alpha, One); + | ^^^ enum variant + +error[E0609]: no field named `1` on enum variant `Alpha::Two` + --> $DIR/offset-of-enum.rs:14:23 + | +LL | offset_of!(Alpha, Two.1); + | ^^^ - ...does not have this field + | | + | this enum variant... + +error[E0609]: no field named `foo` on enum variant `Alpha::Two` + --> $DIR/offset-of-enum.rs:15:23 + | +LL | offset_of!(Alpha, Two.foo); + | ^^^ --- ...does not have this field + | | + | this enum variant... + +error[E0599]: no variant named `NonExistent` found for enum `Alpha` + --> $DIR/offset-of-enum.rs:16:23 + | +LL | offset_of!(Alpha, NonExistent); + | ^^^^^^^^^^^ variant not found -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0573, E0609. -For more information about an error, try `rustc --explain E0573`. +Some errors have detailed explanations: E0412, E0573, E0599, E0609, E0795. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index 6b1a16ba62b67..6fa30d63fb869 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -8,13 +8,20 @@ mod m { pub public: u8, private: u8, } + #[repr(C)] pub struct FooTuple(pub u8, u8); + #[repr(C)] struct Bar { pub public: u8, private: u8, } + + pub enum Baz { + Var1(Foo), + Var2(u64), + } } fn main() { @@ -25,4 +32,8 @@ fn main() { offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private //~| ERROR field `private` of struct `Bar` is private + + offset_of!(m::Baz, Var1.0.public); + offset_of!(m::Baz, Var1.0.private); //~ ERROR field `private` of struct `Foo` is private + offset_of!(m::Baz, Var2.0); } diff --git a/tests/ui/offset-of/offset-of-private.stderr b/tests/ui/offset-of/offset-of-private.stderr index 0674b58f8608c..930e30e6390f5 100644 --- a/tests/ui/offset-of/offset-of-private.stderr +++ b/tests/ui/offset-of/offset-of-private.stderr @@ -1,46 +1,52 @@ error[E0603]: struct `Bar` is private - --> $DIR/offset-of-private.rs:25:19 + --> $DIR/offset-of-private.rs:32:19 | LL | offset_of!(m::Bar, public); | ^^^ private struct | note: the struct `Bar` is defined here - --> $DIR/offset-of-private.rs:14:5 + --> $DIR/offset-of-private.rs:16:5 | LL | struct Bar { | ^^^^^^^^^^ error[E0603]: struct `Bar` is private - --> $DIR/offset-of-private.rs:26:19 + --> $DIR/offset-of-private.rs:33:19 | LL | offset_of!(m::Bar, private); | ^^^ private struct | note: the struct `Bar` is defined here - --> $DIR/offset-of-private.rs:14:5 + --> $DIR/offset-of-private.rs:16:5 | LL | struct Bar { | ^^^^^^^^^^ error[E0616]: field `private` of struct `Foo` is private - --> $DIR/offset-of-private.rs:22:24 + --> $DIR/offset-of-private.rs:29:24 | LL | offset_of!(m::Foo, private); | ^^^^^^^ private field error[E0616]: field `1` of struct `FooTuple` is private - --> $DIR/offset-of-private.rs:24:29 + --> $DIR/offset-of-private.rs:31:29 | LL | offset_of!(m::FooTuple, 1); | ^ private field error[E0616]: field `private` of struct `Bar` is private - --> $DIR/offset-of-private.rs:26:24 + --> $DIR/offset-of-private.rs:33:24 | LL | offset_of!(m::Bar, private); | ^^^^^^^ private field -error: aborting due to 5 previous errors +error[E0616]: field `private` of struct `Foo` is private + --> $DIR/offset-of-private.rs:37:31 + | +LL | offset_of!(m::Baz, Var1.0.private); + | ^^^^^^^ private field + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0603, E0616. For more information about an error, try `rustc --explain E0603`.