Skip to content
/ rust Public
forked from rust-lang/rust

Commit 2feabbb

Browse files
authored
Rollup merge of rust-lang#65389 - ecstatic-morse:zero-sized-array-no-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.
2 parents 2abce06 + c08a871 commit 2feabbb

File tree

3 files changed

+30
-13
lines changed

3 files changed

+30
-13
lines changed

src/librustc/ty/util.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,9 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
10961096

10971097
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
10981098

1099+
// Zero-length arrays never contain anything to drop.
1100+
ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false,
1101+
10991102
// Structural recursion.
11001103
ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
11011104

src/librustc_mir/dataflow/impls/indirect_mutation.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -104,25 +104,16 @@ impl<'tcx> TransferFunction<'_, '_, 'tcx> {
104104
kind: mir::BorrowKind,
105105
borrowed_place: &mir::Place<'tcx>,
106106
) -> bool {
107-
let borrowed_ty = borrowed_place.ty(self.body, self.tcx).ty;
108-
109-
// Zero-sized types cannot be mutated, since there is nothing inside to mutate.
110-
//
111-
// FIXME: For now, we only exempt arrays of length zero. We need to carefully
112-
// consider the effects before extending this to all ZSTs.
113-
if let ty::Array(_, len) = borrowed_ty.kind {
114-
if len.try_eval_usize(self.tcx, self.param_env) == Some(0) {
115-
return false;
116-
}
117-
}
118-
119107
match kind {
120108
mir::BorrowKind::Mut { .. } => true,
121109

122110
| mir::BorrowKind::Shared
123111
| mir::BorrowKind::Shallow
124112
| mir::BorrowKind::Unique
125-
=> !borrowed_ty.is_freeze(self.tcx, self.param_env, DUMMY_SP),
113+
=> !borrowed_place
114+
.ty(self.body, self.tcx)
115+
.ty
116+
.is_freeze(self.tcx, self.param_env, DUMMY_SP),
126117
}
127118
}
128119
}

src/test/ui/consts/issue-65348.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// check-pass
2+
3+
struct Generic<T>(T);
4+
5+
impl<T> Generic<T> {
6+
const ARRAY: [T; 0] = [];
7+
const NEWTYPE_ARRAY: Generic<[T; 0]> = Generic([]);
8+
const ARRAY_FIELD: Generic<(i32, [T; 0])> = Generic((0, []));
9+
}
10+
11+
pub const fn array<T>() -> &'static T {
12+
&Generic::<T>::ARRAY[0]
13+
}
14+
15+
pub const fn newtype_array<T>() -> &'static T {
16+
&Generic::<T>::NEWTYPE_ARRAY.0[0]
17+
}
18+
19+
pub const fn array_field<T>() -> &'static T {
20+
&(Generic::<T>::ARRAY_FIELD.0).1[0]
21+
}
22+
23+
fn main() {}

0 commit comments

Comments
 (0)