Rollup merge of #65389 - ecstatic-morse:zero-sized-array-no-drop, r=eddyb

Return `false` from `needs_drop` for all zero-sized arrays.

Resolves #65348.

This changes the result of the `needs_drop` query from `true` to `false` for types such as `[Box<i32>; 0]`. I believe this change to be sound because a zero-sized array can never actually hold a value. This is an elegant way of resolving #65348 and #64945, but obviously it has much broader implications.
This commit is contained in:
Tyler Mandry 2019-10-15 16:07:53 -07:00 committed by GitHub
commit bbcf66a4a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 13 deletions

View file

@ -1109,6 +1109,9 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
// Zero-length arrays never contain anything to drop.
ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false,
// Structural recursion.
ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),

View file

@ -104,25 +104,16 @@ impl<'tcx> TransferFunction<'_, '_, 'tcx> {
kind: mir::BorrowKind,
borrowed_place: &mir::Place<'tcx>,
) -> bool {
let borrowed_ty = borrowed_place.ty(self.body, self.tcx).ty;
// Zero-sized types cannot be mutated, since there is nothing inside to mutate.
//
// FIXME: For now, we only exempt arrays of length zero. We need to carefully
// consider the effects before extending this to all ZSTs.
if let ty::Array(_, len) = borrowed_ty.kind {
if len.try_eval_usize(self.tcx, self.param_env) == Some(0) {
return false;
}
}
match kind {
mir::BorrowKind::Mut { .. } => true,
| mir::BorrowKind::Shared
| mir::BorrowKind::Shallow
| mir::BorrowKind::Unique
=> !borrowed_ty.is_freeze(self.tcx, self.param_env, DUMMY_SP),
=> !borrowed_place
.ty(self.body, self.tcx)
.ty
.is_freeze(self.tcx, self.param_env, DUMMY_SP),
}
}
}

View file

@ -0,0 +1,23 @@
// check-pass
struct Generic<T>(T);
impl<T> Generic<T> {
const ARRAY: [T; 0] = [];
const NEWTYPE_ARRAY: Generic<[T; 0]> = Generic([]);
const ARRAY_FIELD: Generic<(i32, [T; 0])> = Generic((0, []));
}
pub const fn array<T>() -> &'static T {
&Generic::<T>::ARRAY[0]
}
pub const fn newtype_array<T>() -> &'static T {
&Generic::<T>::NEWTYPE_ARRAY.0[0]
}
pub const fn array_field<T>() -> &'static T {
&(Generic::<T>::ARRAY_FIELD.0).1[0]
}
fn main() {}