@@ -4,6 +4,7 @@ use std::{
44 cmp:: { self , Ordering } ,
55 iter,
66 num:: NonZeroUsize ,
7+ ops:: Bound ,
78} ;
89
910use chalk_ir:: TyKind ;
@@ -18,6 +19,8 @@ use hir_def::{
1819} ;
1920use la_arena:: { ArenaMap , RawIdx } ;
2021
22+ struct X ( Option < NonZeroUsize > ) ;
23+
2124use crate :: {
2225 db:: HirDatabase ,
2326 lang_items:: is_unsafe_cell,
@@ -137,7 +140,38 @@ pub fn layout_of_adt_query(
137140 Abi :: Aggregate { sized : _ } => { }
138141 }
139142 st. largest_niche = None ;
143+ return Ok ( st) ;
144+ }
145+
146+ let ( start, end) = layout_scalar_valid_range ( db, def) ;
147+ match st. abi {
148+ Abi :: Scalar ( ref mut scalar) | Abi :: ScalarPair ( ref mut scalar, _) => {
149+ if let Bound :: Included ( start) = start {
150+ let valid_range = scalar. valid_range_mut ( ) ;
151+ valid_range. start = start;
152+ }
153+ if let Bound :: Included ( end) = end {
154+ let valid_range = scalar. valid_range_mut ( ) ;
155+ valid_range. end = end;
156+ }
157+ // Update `largest_niche` if we have introduced a larger niche.
158+ let niche = Niche :: from_scalar ( dl, Size :: ZERO , * scalar) ;
159+ if let Some ( niche) = niche {
160+ match st. largest_niche {
161+ Some ( largest_niche) => {
162+ // Replace the existing niche even if they're equal,
163+ // because this one is at a lower offset.
164+ if largest_niche. available ( dl) <= niche. available ( dl) {
165+ st. largest_niche = Some ( niche) ;
166+ }
167+ }
168+ None => st. largest_niche = Some ( niche) ,
169+ }
170+ }
171+ }
172+ _ => user_error ! ( "nonscalar layout for layout_scalar_valid_range" ) ,
140173 }
174+
141175 return Ok ( st) ;
142176 }
143177
@@ -591,6 +625,22 @@ pub fn layout_of_adt_query(
591625 Ok ( best_layout. layout )
592626}
593627
628+ fn layout_scalar_valid_range ( db : & dyn HirDatabase , def : AdtId ) -> ( Bound < u128 > , Bound < u128 > ) {
629+ let attrs = db. attrs ( def. into ( ) ) ;
630+ let get = |name| {
631+ let attr = attrs. by_key ( name) . tt_values ( ) ;
632+ for tree in attr {
633+ if let Some ( x) = tree. token_trees . first ( ) {
634+ if let Ok ( x) = x. to_string ( ) . parse ( ) {
635+ return Bound :: Included ( x) ;
636+ }
637+ }
638+ }
639+ Bound :: Unbounded
640+ } ;
641+ ( get ( "rustc_layout_scalar_valid_range_start" ) , get ( "rustc_layout_scalar_valid_range_end" ) )
642+ }
643+
594644pub fn layout_of_adt_recover (
595645 _: & dyn HirDatabase ,
596646 _: & [ String ] ,
0 commit comments