mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 03:03:21 +00:00
support nonzero* niche optimizations
This commit is contained in:
parent
86b5b609f1
commit
f2c9502185
@ -4,6 +4,7 @@ use std::{
|
||||
cmp::{self, Ordering},
|
||||
iter,
|
||||
num::NonZeroUsize,
|
||||
ops::Bound,
|
||||
};
|
||||
|
||||
use chalk_ir::TyKind;
|
||||
@ -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,
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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],
|
||||
|
@ -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(
|
||||
|
@ -29,6 +29,7 @@
|
||||
//! index: sized
|
||||
//! iterator: option
|
||||
//! iterators: iterator, fn
|
||||
//! non_zero:
|
||||
//! option:
|
||||
//! ord: eq, option
|
||||
//! pin:
|
||||
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user