@@ -30,11 +30,13 @@ pub fn provide(providers: &mut Providers) {
3030
3131#[ instrument( skip( tcx) , level = "debug" ) ]
3232fn 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 )
3634}
3735
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+
3840#[ instrument( skip( tcx, query) , level = "debug" ) ]
3941fn naive_layout_of < ' tcx > (
4042 tcx : TyCtxt < ' tcx > ,
@@ -163,7 +165,6 @@ fn naive_layout_of_uncached<'tcx>(
163165 // Potentially-wide pointers.
164166 ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
165167 let data_ptr = scalar ( Pointer ( AddressSpace :: DATA ) ) ;
166-
167168 if let Some ( metadata) = ptr_metadata_scalar ( cx, pointee) ? {
168169 // Effectively a (ptr, meta) tuple.
169170 data_ptr
@@ -322,15 +323,36 @@ fn layout_of_uncached<'tcx>(
322323 ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
323324 let mut data_ptr = scalar_unit ( Pointer ( AddressSpace :: DATA ) ) ;
324325 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 ,
329330 // 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+ }
331337 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 ( ) } ;
334356 }
335357
336358 if let Some ( metadata) = ptr_metadata_scalar ( cx, pointee) ? {
0 commit comments