Skip to content

Commit df7c1c7

Browse files
committed
basic impl of core::mem::Align
1 parent 7e46c5f commit df7c1c7

10 files changed

Lines changed: 176 additions & 1 deletion

File tree

compiler/rustc_hir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ language_item_table! {
443443
FieldBase, sym::field_base, field_base, Target::AssocTy, GenericRequirement::Exact(0);
444444
FieldType, sym::field_type, field_type, Target::AssocTy, GenericRequirement::Exact(0);
445445
FieldOffset, sym::field_offset, field_offset, Target::AssocConst, GenericRequirement::Exact(0);
446+
AlignType, sym::align_type, align_type, Target::Struct, GenericRequirement::Exact(1);
446447
}
447448

448449
/// The requirement imposed on the generics of a lang item

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ symbols! {
374374
align,
375375
align_of,
376376
align_of_val,
377+
align_type,
377378
alignment,
378379
all,
379380
alloc,

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,10 +686,25 @@ fn layout_of_uncached<'tcx>(
686686
!tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, typing_env)
687687
});
688688

689+
let mut repr = def.repr();
690+
691+
// FIXME: should this have a flag on the adtdef?
692+
if tcx.is_lang_item(def.did(), hir::LangItem::AlignType) {
693+
let align_value = extract_const_value(cx, ty, args.const_at(0))?
694+
.try_to_target_usize(tcx)
695+
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
696+
697+
// FIXME: actual error message
698+
let align = abi::Align::from_bytes(align_value)
699+
.map_err(|_| error(cx, LayoutError::Unknown(ty)))?;
700+
701+
repr.align = Some(align);
702+
}
703+
689704
let layout = cx
690705
.calc
691706
.layout_of_struct_or_enum(
692-
&def.repr(),
707+
&repr,
693708
&variants,
694709
def.is_enum(),
695710
is_special_no_niche,

library/core/src/mem/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,3 +1533,16 @@ pub const unsafe fn conjure_zst<T>() -> T {
15331533
MaybeUninit::uninit().assume_init()
15341534
}
15351535
}
1536+
1537+
/// Zero-sized type with an alignment from its const generic parameter.
1538+
///
1539+
/// ## Layout:
1540+
/// If `N` is a valid alignment then the following are guaranteed:
1541+
/// * `size_of::<Align<N>>() == 0`
1542+
/// * `align_of::<Align<N>>() == N`
1543+
///
1544+
/// Otherwise, `Align<N>` does not have a valid layout and compilation will fail.
1545+
#[unstable(feature = "align_type", issue = "none")]
1546+
#[lang = "align_type"]
1547+
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1548+
pub struct Align<const N: usize>;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// test that layout cycles involving Align error and don't ICE
2+
#![feature(align_type)]
3+
4+
use std::mem::Align;
5+
6+
struct Evil {
7+
align: Align<{align_of::<Evil>()}>, //~ ERROR cycle detected
8+
}
9+
10+
fn main() {}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0391]: cycle detected when evaluating type-level constant
2+
--> $DIR/cycle.rs:7:18
3+
|
4+
LL | align: Align<{align_of::<Evil>()}>,
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: ...which requires const-evaluating + checking `Evil::align::{constant#0}`...
8+
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
9+
note: ...which requires simplifying constant for the type system `core::mem::SizedTypeProperties::ALIGN`...
10+
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
11+
note: ...which requires const-evaluating + checking `core::mem::SizedTypeProperties::ALIGN`...
12+
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
13+
= note: ...which requires computing layout of `Evil`...
14+
= note: ...which requires computing layout of `core::mem::Align<{align_of::<Evil>()}>`...
15+
note: ...which requires normalizing `core::mem::Align<{align_of::<Evil>()}>`...
16+
--> $DIR/cycle.rs:7:18
17+
|
18+
LL | align: Align<{align_of::<Evil>()}>,
19+
| ^^^^^^^^^^^^^^^^^^^^
20+
= note: ...which again requires evaluating type-level constant, completing the cycle
21+
note: cycle used when checking that `Evil` is well-formed
22+
--> $DIR/cycle.rs:7:18
23+
|
24+
LL | align: Align<{align_of::<Evil>()}>,
25+
| ^^^^^^^^^^^^^^^^^^^^
26+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
27+
28+
error: aborting due to 1 previous error
29+
30+
For more information about this error, try `rustc --explain E0391`.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// test that invalid alignments put into Align fail
2+
#![feature(align_type)]
3+
4+
use std::mem::Align;
5+
6+
const MAX_SUPPORTED_ALIGN: usize = 1 << 29;
7+
8+
const _: () = {
9+
// not power of two
10+
align_of::<Align<3>>(); //~? ERROR unknown layout
11+
};
12+
13+
const _: () = {
14+
// too big
15+
align_of::<Align<{MAX_SUPPORTED_ALIGN * 2}>>(); //~? ERROR unknown layout
16+
};
17+
18+
fn main() {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0080]: the type `Align<3>` has an unknown layout
2+
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
3+
|
4+
= note: evaluation of `<std::mem::Align<3> as std::mem::SizedTypeProperties>::ALIGN` failed here
5+
6+
error[E0080]: the type `Align<1073741824>` has an unknown layout
7+
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
8+
|
9+
= note: evaluation of `<std::mem::Align<1073741824> as std::mem::SizedTypeProperties>::ALIGN` failed here
10+
11+
error: aborting due to 2 previous errors
12+
13+
For more information about this error, try `rustc --explain E0080`.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// FIXME: should this pass?
2+
//@ check-pass
3+
#![feature(align_type)]
4+
5+
use std::marker::PhantomData;
6+
use std::mem::Align;
7+
8+
struct TypeFromTheTernaryDimension {
9+
align: Align<3>,
10+
}
11+
12+
struct InsidePhantom {
13+
phantom: PhantomData<Align<9999>>,
14+
}
15+
16+
const _: () = {
17+
assert!(size_of::<InsidePhantom>() == 0);
18+
assert!(align_of::<InsidePhantom>() == 1);
19+
};
20+
21+
fn main() {}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// test that reasonable usage of Align works as expected
2+
//@ check-pass
3+
#![feature(align_type)]
4+
5+
use std::mem::Align;
6+
7+
struct ContainsJustAlign {
8+
align: Align<8>
9+
}
10+
11+
struct WithAlignType {
12+
a: [u8; 4],
13+
b: u32,
14+
c: *const (),
15+
16+
align: Align<16>
17+
}
18+
19+
#[repr(align(16))]
20+
struct WithReprAlign {
21+
a: [u8; 4],
22+
b: u32,
23+
c: *const (),
24+
}
25+
26+
const XKCD_CERTIFIED_RANDOM_NUMBER: usize = 4;
27+
const MAX_SUPPORTED_ALIGN: usize = 1 << 29;
28+
29+
const _: () = {
30+
// FIXME: should this fail?
31+
assert!(size_of::<Align<0>>() == 0);
32+
assert!(align_of::<Align<0>>() == 1);
33+
34+
assert!(size_of::<Align<1>>() == 0);
35+
assert!(align_of::<Align<1>>() == 1);
36+
37+
assert!(size_of::<Align<64>>() == 0);
38+
assert!(align_of::<Align<64>>() == 64);
39+
40+
assert!(size_of::<Align<XKCD_CERTIFIED_RANDOM_NUMBER>>() == 0);
41+
assert!(align_of::<Align<XKCD_CERTIFIED_RANDOM_NUMBER>>() == XKCD_CERTIFIED_RANDOM_NUMBER);
42+
43+
assert!(size_of::<Align<MAX_SUPPORTED_ALIGN>>() == 0);
44+
assert!(align_of::<Align<MAX_SUPPORTED_ALIGN>>() == MAX_SUPPORTED_ALIGN);
45+
46+
assert!(size_of::<ContainsJustAlign>() == 0);
47+
assert!(align_of::<ContainsJustAlign>() == 8);
48+
49+
assert!(size_of::<WithAlignType>() == size_of::<WithReprAlign>());
50+
assert!(align_of::<WithAlignType>() == size_of::<WithReprAlign>());
51+
};
52+
53+
fn main() {}

0 commit comments

Comments
 (0)