Skip to content

Commit

Permalink
Rollup merge of rust-lang#65389 - ecstatic-morse:zero-sized-array-no-…
Browse files Browse the repository at this point in the history
…drop, r=eddyb

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

Resolves rust-lang#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 rust-lang#65348 and rust-lang#64945, but obviously it has much broader implications.
  • Loading branch information
tmandry committed Oct 15, 2019
2 parents 820fb7c + c08a871 commit bbcf66a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down
17 changes: 4 additions & 13 deletions src/librustc_mir/dataflow/impls/indirect_mutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/consts/issue-65348.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit bbcf66a

Please sign in to comment.