Skip to content

Commit 674f94a

Browse files
committed
partial enum & union support
1 parent 7547da8 commit 674f94a

File tree

4 files changed

+51
-16
lines changed

4 files changed

+51
-16
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,21 +288,24 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
288288
let container = self.structurally_resolve_type(span, current_container);
289289

290290
match container.kind() {
291-
ty::Adt(container_def, args)
292-
if container_def.is_enum() && field_path_kind == FieldPathKind::OffsetOf =>
293-
{
291+
ty::Adt(container_def, args) if container_def.is_enum() => {
294292
let block = self.tcx.local_def_id_to_hir_id(self.body_id);
295293
let (ident, _def_scope) =
296294
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
297295

298-
if !self.tcx.features().offset_of_enum() {
299-
rustc_session::parse::feature_err(
300-
&self.tcx.sess,
301-
sym::offset_of_enum,
302-
ident.span,
303-
"using enums in offset_of is experimental",
304-
)
305-
.emit();
296+
match field_path_kind {
297+
FieldPathKind::OffsetOf => {
298+
if !self.tcx.features().offset_of_enum() {
299+
rustc_session::parse::feature_err(
300+
&self.tcx.sess,
301+
sym::offset_of_enum,
302+
ident.span,
303+
"using enums in offset_of is experimental",
304+
)
305+
.emit();
306+
}
307+
}
308+
FieldPathKind::FieldOf => {}
306309
}
307310

308311
let Some((index, variant)) = container_def

library/std/tests/field-projections-basic.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ pub struct Foo {
1111
pub z: (usize, usize),
1212
}
1313

14-
pub fn project_ref<F: Field>(r: &F::Base) -> &F::Type
14+
/// # Safety
15+
///
16+
/// All container types of `F` must be structs or tuples.
17+
pub unsafe fn project_ref<F: Field>(r: &F::Base) -> &F::Type
1518
where
1619
F::Type: Sized,
1720
{
@@ -21,10 +24,10 @@ where
2124
#[test]
2225
fn foo() {
2326
let foo = Foo { x: 42, y: 24, z: (43, 44) };
24-
let x = project_ref::<field_of!(Foo, x)>(&foo);
25-
let y = project_ref::<field_of!(Foo, y)>(&foo);
26-
let z0 = project_ref::<field_of!(Foo, z.0)>(&foo);
27-
let z1 = project_ref::<field_of!(Foo, z.1)>(&foo);
27+
let x = unsafe { project_ref::<field_of!(Foo, x)>(&foo) };
28+
let y = unsafe { project_ref::<field_of!(Foo, y)>(&foo) };
29+
let z0 = unsafe { project_ref::<field_of!(Foo, z.0)>(&foo) };
30+
let z1 = unsafe { project_ref::<field_of!(Foo, z.1)>(&foo) };
2831
assert_eq!(*x, 42);
2932
assert_eq!(*y, 24);
3033
assert_eq!(<field_of!(Foo, x)>::OFFSET, offset_of!(Foo, x));

tests/ui/field_projections/enum.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ run-fail
2+
#![allow(incomplete_features)]
3+
#![feature(field_projections)]
4+
5+
use std::field::{UnalignedField, field_of};
6+
7+
pub enum Foo {
8+
A { a: isize, b: usize },
9+
}
10+
11+
fn main() {
12+
assert_eq!(<field_of!(Foo, A.a)>::OFFSET, <field_of!(Foo, A.b)>::OFFSET);
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ run-pass
2+
#![allow(incomplete_features, dead_code)]
3+
#![feature(field_projections)]
4+
5+
use std::field::{UnalignedField, field_of};
6+
7+
pub union Foo {
8+
a: isize,
9+
b: usize,
10+
}
11+
12+
type X = field_of!(Foo, a);
13+
14+
fn main() {
15+
assert_eq!(X::OFFSET, <field_of!(Foo, b)>::OFFSET);
16+
}

0 commit comments

Comments
 (0)