diff options
| author | Tyler Mandry <tmandry@gmail.com> | 2019-10-15 16:07:53 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-15 16:07:53 -0700 |
| commit | bbcf66a4a177c1756d5b6845933e6cb06aa21b2c (patch) | |
| tree | e8afbeeb22cc0a0ddc3e088dadfd0aa5150d35e9 | |
| parent | 820fb7ccbf2fa6116ce09a178b2deb9e9b736704 (diff) | |
| parent | c08a8713381ed67caea826a793145240cd873081 (diff) | |
| download | rust-bbcf66a4a177c1756d5b6845933e6cb06aa21b2c.tar.gz rust-bbcf66a4a177c1756d5b6845933e6cb06aa21b2c.zip | |
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.
| -rw-r--r-- | src/librustc/ty/util.rs | 3 | ||||
| -rw-r--r-- | src/librustc_mir/dataflow/impls/indirect_mutation.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/consts/issue-65348.rs | 23 |
3 files changed, 30 insertions, 13 deletions
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 5dbb7abc582..e1eab2c6579 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -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), diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs index 990425c3252..bc09e327179 100644 --- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs +++ b/src/librustc_mir/dataflow/impls/indirect_mutation.rs @@ -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), } } } diff --git a/src/test/ui/consts/issue-65348.rs b/src/test/ui/consts/issue-65348.rs new file mode 100644 index 00000000000..5eafa831d63 --- /dev/null +++ b/src/test/ui/consts/issue-65348.rs @@ -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() {} |
