Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/layout/adt.rs')
-rw-r--r--crates/hir-ty/src/layout/adt.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index e353034eb9..9244353f3a 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -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],