@@ -30,11 +30,13 @@ pub fn provide(providers: &mut Providers) {
30
30
31
31
#[ instrument( skip( tcx) , level = "debug" ) ]
32
32
fn reference_niches_policy < ' tcx > ( tcx : TyCtxt < ' tcx > , _: LocalCrate ) -> ReferenceNichePolicy {
33
- const DEFAULT : ReferenceNichePolicy = ReferenceNichePolicy { size : false , align : false } ;
34
-
35
- tcx. sess . opts . unstable_opts . reference_niches . unwrap_or ( DEFAULT )
33
+ tcx. sess . opts . unstable_opts . reference_niches . unwrap_or ( DEFAULT_REF_NICHES )
36
34
}
37
35
36
+ /// The reference niche policy for builtin types, and for types in
37
+ /// crates not specifying `-Z reference-niches`.
38
+ const DEFAULT_REF_NICHES : ReferenceNichePolicy = ReferenceNichePolicy { size : false , align : false } ;
39
+
38
40
#[ instrument( skip( tcx, query) , level = "debug" ) ]
39
41
fn naive_layout_of < ' tcx > (
40
42
tcx : TyCtxt < ' tcx > ,
@@ -163,7 +165,6 @@ fn naive_layout_of_uncached<'tcx>(
163
165
// Potentially-wide pointers.
164
166
ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
165
167
let data_ptr = scalar ( Pointer ( AddressSpace :: DATA ) ) ;
166
-
167
168
if let Some ( metadata) = ptr_metadata_scalar ( cx, pointee) ? {
168
169
// Effectively a (ptr, meta) tuple.
169
170
data_ptr
@@ -322,15 +323,36 @@ fn layout_of_uncached<'tcx>(
322
323
ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
323
324
let mut data_ptr = scalar_unit ( Pointer ( AddressSpace :: DATA ) ) ;
324
325
if !ty. is_unsafe_ptr ( ) {
325
- match cx . naive_layout_of ( pointee ) {
326
- // TODO(reference_niches): actually use the naive layout to set
327
- // reference niches; the query is still kept to for testing purposes.
328
- Ok ( _ ) => ( ) ,
326
+ // Calling `layout_of` here would cause a query cycle for recursive types;
327
+ // so use a conservative estimate that doesn't look past references.
328
+ let naive = match cx . naive_layout_of ( pointee ) {
329
+ Ok ( n ) => n . layout ,
329
330
// This can happen when computing the `SizeSkeleton` of a generic type.
330
- Err ( LayoutError :: Unknown ( _) ) => ( ) ,
331
+ Err ( LayoutError :: Unknown ( _) ) => {
332
+ // TODO(reference_niches): this is *very* incorrect, but we can't
333
+ // return an error here; this would break transmute checks.
334
+ // We need some other solution.
335
+ NaiveLayout :: EMPTY
336
+ }
331
337
Err ( err) => return Err ( err) ,
332
- }
333
- data_ptr. valid_range_mut ( ) . start = 1 ;
338
+ } ;
339
+
340
+ let niches = match * pointee. kind ( ) {
341
+ ty:: FnDef ( def, ..)
342
+ | ty:: Foreign ( def)
343
+ | ty:: Generator ( def, ..)
344
+ | ty:: Closure ( def, ..) => tcx. reference_niches_policy ( def. krate ) ,
345
+ ty:: Adt ( def, _) => tcx. reference_niches_policy ( def. did ( ) . krate ) ,
346
+ _ => DEFAULT_REF_NICHES ,
347
+ } ;
348
+
349
+ let ( min_addr, max_addr) = dl. address_range_for (
350
+ if niches. size { naive. min_size } else { Size :: ZERO } ,
351
+ if niches. align { naive. min_align } else { Align :: ONE } ,
352
+ ) ;
353
+
354
+ * data_ptr. valid_range_mut ( ) =
355
+ WrappingRange { start : min_addr. into ( ) , end : max_addr. into ( ) } ;
334
356
}
335
357
336
358
if let Some ( metadata) = ptr_metadata_scalar ( cx, pointee) ? {
0 commit comments