1
Fork 0

Auto merge of #106934 - DrMeepster:offset_of, r=WaffleLapkin

Add offset_of! macro (RFC 3308)

Implements https://github.com/rust-lang/rfcs/pull/3308 (tracking issue #106655) by adding the built in macro `core::mem::offset_of`. Two of the future possibilities are also implemented:

* Nested field accesses (without array indexing)
* DST support (for `Sized` fields)

I wrote this a few months ago, before the RFC merged. Now that it's merged, I decided to rebase and finish it.

cc `@thomcc` (RFC author)
This commit is contained in:
bors 2023-04-22 00:10:44 +00:00
commit 80a2ec49a4
83 changed files with 1355 additions and 42 deletions

View file

@ -557,6 +557,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::ConstBlock { .. }
| ExprKind::StaticRef { .. }
| ExprKind::InlineAsm { .. }
| ExprKind::OffsetOf { .. }
| ExprKind::Yield { .. }
| ExprKind::ThreadLocalRef(_)
| ExprKind::Call { .. } => {

View file

@ -481,6 +481,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}))))
}
ExprKind::OffsetOf { container, fields } => {
block.and(Rvalue::NullaryOp(NullOp::OffsetOf(fields), container))
}
ExprKind::Literal { .. }
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }

View file

@ -67,7 +67,8 @@ impl Category {
| ExprKind::Repeat { .. }
| ExprKind::Assign { .. }
| ExprKind::AssignOp { .. }
| ExprKind::ThreadLocalRef(_) => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
| ExprKind::ThreadLocalRef(_)
| ExprKind::OffsetOf { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
ExprKind::ConstBlock { .. }
| ExprKind::Literal { .. }

View file

@ -561,7 +561,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::ZstLiteral { .. }
| ExprKind::ConstParam { .. }
| ExprKind::ThreadLocalRef(_)
| ExprKind::StaticRef { .. } => {
| ExprKind::StaticRef { .. }
| ExprKind::OffsetOf { .. } => {
debug_assert!(match Category::of(&expr.kind).unwrap() {
// should be handled above
Category::Rvalue(RvalueFunc::Into) => false,

View file

@ -323,6 +323,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
| ExprKind::Box { .. }
| ExprKind::If { .. }
| ExprKind::InlineAsm { .. }
| ExprKind::OffsetOf { .. }
| ExprKind::LogicalOp { .. }
| ExprKind::Use { .. } => {
// We don't need to save the old value and restore it

View file

@ -664,6 +664,14 @@ impl<'tcx> Cx<'tcx> {
line_spans: asm.line_spans,
})),
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());
ExprKind::OffsetOf { container, fields }
}
hir::ExprKind::ConstBlock(ref anon_const) => {
let ty = self.typeck_results().node_type(anon_const.hir_id);
let did = anon_const.def_id.to_def_id();

View file

@ -519,6 +519,19 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
self.print_inline_asm_expr(&**expr, depth_lvl + 2);
print_indented!(self, "}", depth_lvl);
}
OffsetOf { container, fields } => {
print_indented!(self, "OffsetOf {", depth_lvl);
print_indented!(self, format!("container: {:?}", container), depth_lvl + 1);
print_indented!(self, "fields: [", depth_lvl + 1);
for field in fields.iter() {
print_indented!(self, format!("{:?}", field), depth_lvl + 2);
print_indented!(self, ",", depth_lvl + 1);
}
print_indented!(self, "]", depth_lvl + 1);
print_indented!(self, "}", depth_lvl);
}
ThreadLocalRef(def_id) => {
print_indented!(self, "ThreadLocalRef {", depth_lvl);
print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);