-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Add Align type with const generic controlled alignment #154730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -374,6 +374,7 @@ symbols! { | |
| align, | ||
| align_of, | ||
| align_of_val, | ||
| align_type, | ||
| alignment, | ||
| all, | ||
| alloc, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // test that layout cycles involving Align error and don't ICE | ||
| #![feature(align_type)] | ||
|
|
||
| use std::mem::Align; | ||
|
|
||
| struct Evil { | ||
| align: Align<{align_of::<Evil>()}>, //~ ERROR cycle detected | ||
| } | ||
|
|
||
| fn main() {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| error[E0391]: cycle detected when evaluating type-level constant | ||
| --> $DIR/cycle.rs:7:18 | ||
| | | ||
| LL | align: Align<{align_of::<Evil>()}>, | ||
| | ^^^^^^^^^^^^^^^^^^^^ | ||
| | | ||
| note: ...which requires const-evaluating + checking `Evil::align::{constant#0}`... | ||
| --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | ||
| note: ...which requires simplifying constant for the type system `core::mem::SizedTypeProperties::ALIGN`... | ||
| --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | ||
| note: ...which requires const-evaluating + checking `core::mem::SizedTypeProperties::ALIGN`... | ||
| --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | ||
| = note: ...which requires computing layout of `Evil`... | ||
| = note: ...which requires computing layout of `core::mem::Align<{align_of::<Evil>()}>`... | ||
| note: ...which requires normalizing `core::mem::Align<{align_of::<Evil>()}>`... | ||
| --> $DIR/cycle.rs:7:18 | ||
| | | ||
| LL | align: Align<{align_of::<Evil>()}>, | ||
| | ^^^^^^^^^^^^^^^^^^^^ | ||
| = note: ...which again requires evaluating type-level constant, completing the cycle | ||
| note: cycle used when checking that `Evil` is well-formed | ||
| --> $DIR/cycle.rs:7:18 | ||
| | | ||
| LL | align: Align<{align_of::<Evil>()}>, | ||
| | ^^^^^^^^^^^^^^^^^^^^ | ||
| = 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 | ||
|
|
||
| error: aborting due to 1 previous error | ||
|
|
||
| For more information about this error, try `rustc --explain E0391`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // test that invalid alignments put into Align fail | ||
| #![feature(align_type)] | ||
|
|
||
| use std::mem::Align; | ||
|
|
||
| const MAX_SUPPORTED_ALIGN: usize = 1 << 29; | ||
|
|
||
| const _: () = { | ||
| // not power of two | ||
| align_of::<Align<3>>(); //~? ERROR unknown layout | ||
| }; | ||
|
|
||
| const _: () = { | ||
| // too big | ||
| align_of::<Align<{MAX_SUPPORTED_ALIGN * 2}>>(); //~? ERROR unknown layout | ||
| }; | ||
|
|
||
| fn main() {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| error[E0080]: the type `Align<3>` has an unknown layout | ||
| --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | ||
| | | ||
| = note: evaluation of `<std::mem::Align<3> as std::mem::SizedTypeProperties>::ALIGN` failed here | ||
|
|
||
| error[E0080]: the type `Align<1073741824>` has an unknown layout | ||
| --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | ||
| | | ||
| = note: evaluation of `<std::mem::Align<1073741824> as std::mem::SizedTypeProperties>::ALIGN` failed here | ||
|
|
||
| error: aborting due to 2 previous errors | ||
|
|
||
| For more information about this error, try `rustc --explain E0080`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // FIXME: should this pass? | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My instinct is that it definitely shouldn't pass, but maybe it doesn't fail elegantly -- perhaps it fails in the same way that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, types that are too large don't fail in these positions either
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, because it's just a check build or something? If it's consistent with malformed arrays that's probably fine -- for now at least. |
||
| //@ check-pass | ||
| #![feature(align_type)] | ||
|
|
||
| use std::marker::PhantomData; | ||
| use std::mem::Align; | ||
|
|
||
| struct TypeFromTheTernaryDimension { | ||
| align: Align<3>, | ||
| } | ||
|
|
||
| struct InsidePhantom { | ||
| phantom: PhantomData<Align<9999>>, | ||
| } | ||
|
|
||
| const _: () = { | ||
| assert!(size_of::<InsidePhantom>() == 0); | ||
| assert!(align_of::<InsidePhantom>() == 1); | ||
| }; | ||
|
|
||
| fn main() {} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // test that reasonable usage of Align works as expected | ||
| //@ check-pass | ||
| #![feature(align_type)] | ||
|
|
||
| use std::mem::Align; | ||
|
|
||
| struct ContainsJustAlign { | ||
| align: Align<8> | ||
| } | ||
|
|
||
| struct WithAlignType { | ||
| a: [u8; 4], | ||
| b: u32, | ||
| c: *const (), | ||
|
|
||
| align: Align<16> | ||
| } | ||
|
|
||
| #[repr(align(16))] | ||
| struct WithReprAlign { | ||
| a: [u8; 4], | ||
| b: u32, | ||
| c: *const (), | ||
| } | ||
|
|
||
| const XKCD_CERTIFIED_RANDOM_NUMBER: usize = 4; | ||
| const MAX_SUPPORTED_ALIGN: usize = 1 << 29; | ||
|
|
||
| const _: () = { | ||
| // FIXME: should this fail? | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, same as (And how https://doc.rust-lang.org/std/primitive.usize.html#method.is_power_of_two does not treat zero as a power of two.) |
||
| assert!(size_of::<Align<0>>() == 0); | ||
| assert!(align_of::<Align<0>>() == 1); | ||
|
|
||
| assert!(size_of::<Align<1>>() == 0); | ||
| assert!(align_of::<Align<1>>() == 1); | ||
|
|
||
| assert!(size_of::<Align<64>>() == 0); | ||
| assert!(align_of::<Align<64>>() == 64); | ||
|
|
||
| assert!(size_of::<Align<XKCD_CERTIFIED_RANDOM_NUMBER>>() == 0); | ||
| assert!(align_of::<Align<XKCD_CERTIFIED_RANDOM_NUMBER>>() == XKCD_CERTIFIED_RANDOM_NUMBER); | ||
|
|
||
| assert!(size_of::<Align<MAX_SUPPORTED_ALIGN>>() == 0); | ||
| assert!(align_of::<Align<MAX_SUPPORTED_ALIGN>>() == MAX_SUPPORTED_ALIGN); | ||
|
|
||
| assert!(size_of::<ContainsJustAlign>() == 0); | ||
| assert!(align_of::<ContainsJustAlign>() == 8); | ||
|
|
||
| assert!(size_of::<WithAlignType>() == size_of::<WithReprAlign>()); | ||
| assert!(align_of::<WithAlignType>() == size_of::<WithReprAlign>()); | ||
| }; | ||
|
|
||
| fn main() {} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My instinct is no, because everything other than layout should just treat it as a normal type with a generic-dependent layout, never switch on some type flag to detect it.