@@ -4,6 +4,7 @@ use std::{
4
4
cmp:: { self , Ordering } ,
5
5
iter,
6
6
num:: NonZeroUsize ,
7
+ ops:: Bound ,
7
8
} ;
8
9
9
10
use chalk_ir:: TyKind ;
@@ -18,6 +19,8 @@ use hir_def::{
18
19
} ;
19
20
use la_arena:: { ArenaMap , RawIdx } ;
20
21
22
+ struct X ( Option < NonZeroUsize > ) ;
23
+
21
24
use crate :: {
22
25
db:: HirDatabase ,
23
26
lang_items:: is_unsafe_cell,
@@ -137,7 +140,38 @@ pub fn layout_of_adt_query(
137
140
Abi :: Aggregate { sized : _ } => { }
138
141
}
139
142
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" ) ,
140
173
}
174
+
141
175
return Ok ( st) ;
142
176
}
143
177
@@ -591,6 +625,22 @@ pub fn layout_of_adt_query(
591
625
Ok ( best_layout. layout )
592
626
}
593
627
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
+
594
644
pub fn layout_of_adt_recover (
595
645
_: & dyn HirDatabase ,
596
646
_: & [ String ] ,
0 commit comments