Skip to content

Commit

Permalink
support nonzero* niche optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
HKalbasi committed Dec 3, 2022
1 parent 86b5b60 commit f2c9502
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
50 changes: 50 additions & 0 deletions crates/hir-ty/src/layout/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{
cmp::{self, Ordering},
iter,
num::NonZeroUsize,
ops::Bound,
};

use chalk_ir::TyKind;
Expand All @@ -18,6 +19,8 @@ use hir_def::{
};
use la_arena::{ArenaMap, RawIdx};

struct X(Option<NonZeroUsize>);

use crate::{
db::HirDatabase,
lang_items::is_unsafe_cell,
Expand Down Expand Up @@ -137,7 +140,38 @@ pub fn layout_of_adt_query(
Abi::Aggregate { sized: _ } => {}
}
st.largest_niche = None;
return Ok(st);
}

let (start, end) = layout_scalar_valid_range(db, def);
match st.abi {
Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
if let Bound::Included(start) = start {
let valid_range = scalar.valid_range_mut();
valid_range.start = start;
}
if let Bound::Included(end) = end {
let valid_range = scalar.valid_range_mut();
valid_range.end = end;
}
// Update `largest_niche` if we have introduced a larger niche.
let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
if let Some(niche) = niche {
match st.largest_niche {
Some(largest_niche) => {
// Replace the existing niche even if they're equal,
// because this one is at a lower offset.
if largest_niche.available(dl) <= niche.available(dl) {
st.largest_niche = Some(niche);
}
}
None => st.largest_niche = Some(niche),
}
}
}
_ => user_error!("nonscalar layout for layout_scalar_valid_range"),
}

return Ok(st);
}

Expand Down Expand Up @@ -591,6 +625,22 @@ pub fn layout_of_adt_query(
Ok(best_layout.layout)
}

fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound<u128>, Bound<u128>) {
let attrs = db.attrs(def.into());
let get = |name| {
let attr = attrs.by_key(name).tt_values();
for tree in attr {
if let Some(x) = tree.token_trees.first() {
if let Ok(x) = x.to_string().parse() {
return Bound::Included(x);
}
}
}
Bound::Unbounded
};
(get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end"))
}

pub fn layout_of_adt_recover(
_: &dyn HirDatabase,
_: &[String],
Expand Down
13 changes: 13 additions & 0 deletions crates/hir-ty/src/layout/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,19 @@ fn tuple() {
}
}

#[test]
fn non_zero() {
check_size_and_align(
r#"
//- minicore: non_zero, option
use core::num::NonZeroU8;
struct Goal(Option<NonZeroU8>);
"#,
1,
1,
);
}

#[test]
fn niche_optimization() {
check_size_and_align(
Expand Down
10 changes: 10 additions & 0 deletions crates/test-utils/src/minicore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
//! index: sized
//! iterator: option
//! iterators: iterator, fn
//! non_zero:
//! option:
//! ord: eq, option
//! pin:
Expand Down Expand Up @@ -680,6 +681,15 @@ mod macros {
}
// endregion:derive

// region:non_zero
pub mod num {
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
pub struct NonZeroU8(u8);
}
// endregion:non_zero

// region:bool_impl
#[lang = "bool"]
impl bool {
Expand Down

0 comments on commit f2c9502

Please sign in to comment.