@@ -238,7 +238,7 @@ fn adjust_for_rust_scalar<'tcx>(
238
238
layout : TyAndLayout < ' tcx > ,
239
239
offset : Size ,
240
240
is_return : bool ,
241
- is_drop_target : bool ,
241
+ drop_target_pointee : Option < Ty < ' tcx > > ,
242
242
) {
243
243
// Booleans are always a noundef i1 that needs to be zero-extended.
244
244
if scalar. is_bool ( ) {
@@ -252,14 +252,24 @@ fn adjust_for_rust_scalar<'tcx>(
252
252
}
253
253
254
254
// Only pointer types handled below.
255
- let Scalar :: Initialized { value : Pointer ( _) , valid_range} = scalar else { return } ;
255
+ let Scalar :: Initialized { value : Pointer ( _) , valid_range } = scalar else { return } ;
256
256
257
- if !valid_range. contains ( 0 ) {
257
+ // Set `nonnull` if the validity range excludes zero, or for the argument to `drop_in_place`,
258
+ // which must be nonnull per its documented safety requirements.
259
+ if !valid_range. contains ( 0 ) || drop_target_pointee. is_some ( ) {
258
260
attrs. set ( ArgAttribute :: NonNull ) ;
259
261
}
260
262
261
263
if let Some ( pointee) = layout. pointee_info_at ( & cx, offset) {
262
- if let Some ( kind) = pointee. safe {
264
+ let kind = if let Some ( kind) = pointee. safe {
265
+ Some ( kind)
266
+ } else if let Some ( pointee) = drop_target_pointee {
267
+ // The argument to `drop_in_place` is semantically equivalent to a mutable reference.
268
+ Some ( PointerKind :: MutableRef { unpin : pointee. is_unpin ( cx. tcx , cx. param_env ( ) ) } )
269
+ } else {
270
+ None
271
+ } ;
272
+ if let Some ( kind) = kind {
263
273
attrs. pointee_align = Some ( pointee. align ) ;
264
274
265
275
// `Box` are not necessarily dereferenceable for the entire duration of the function as
@@ -307,18 +317,6 @@ fn adjust_for_rust_scalar<'tcx>(
307
317
attrs. set ( ArgAttribute :: ReadOnly ) ;
308
318
}
309
319
}
310
-
311
- // If this is the argument to `drop_in_place`, the contents of which we fully control as the
312
- // compiler, then we mark this argument as `noalias`, aligned, and dereferenceable. (The
313
- // standard library documents the necessary requirements to uphold these attributes for code
314
- // that calls this method directly.) This can enable better optimizations, such as argument
315
- // promotion.
316
- if is_drop_target {
317
- attrs. set ( ArgAttribute :: NoAlias ) ;
318
- attrs. set ( ArgAttribute :: NonNull ) ;
319
- attrs. pointee_size = pointee. size ;
320
- attrs. pointee_align = Some ( pointee. align ) ;
321
- }
322
320
}
323
321
}
324
322
@@ -383,6 +381,10 @@ fn fn_abi_new_uncached<'tcx>(
383
381
let _entered = span. enter ( ) ;
384
382
let is_return = arg_idx. is_none ( ) ;
385
383
let is_drop_target = is_drop_in_place && arg_idx == Some ( 0 ) ;
384
+ let drop_target_pointee = is_drop_target. then ( || match ty. kind ( ) {
385
+ ty:: RawPtr ( ty:: TypeAndMut { ty, .. } ) => * ty,
386
+ _ => bug ! ( "argument to drop_in_place is not a raw ptr: {:?}" , ty) ,
387
+ } ) ;
386
388
387
389
let layout = cx. layout_of ( ty) ?;
388
390
let layout = if force_thin_self_ptr && arg_idx == Some ( 0 ) {
@@ -403,7 +405,7 @@ fn fn_abi_new_uncached<'tcx>(
403
405
* layout,
404
406
offset,
405
407
is_return,
406
- is_drop_target ,
408
+ drop_target_pointee ,
407
409
) ;
408
410
attrs
409
411
} ) ;
0 commit comments