diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3f8a1a3f79504..f4230116fa3a1 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -54,6 +54,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, scope, &this.thir[value], None)); + if let Some(0) = count.try_eval_usize(this.tcx, this.param_env) { + if let Operand::Move(place) = value_operand { + let success = this.cfg.start_new_block(); + this.cfg.terminate( + block, + source_info, + TerminatorKind::Drop { place, target: success, unwind: None }, + ); + this.diverge_from(block); + block = success; + return block.and(Rvalue::Use(Operand::Constant(Box::new(Constant { + span: expr_span, + user_ty: None, + literal: ty::Const::zero_sized(this.tcx, expr.ty).into(), + })))); + } + } block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Binary { op, lhs, rhs } => { diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs new file mode 100644 index 0000000000000..b14c1b3aa093c --- /dev/null +++ b/src/test/ui/drop/repeat-drop-2.rs @@ -0,0 +1,5 @@ +fn main() { + let foo = String::new(); + let _bar = foo; + let _baz = [foo; 0]; //~ ERROR use of moved value: `foo` [E0382] +} diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr new file mode 100644 index 0000000000000..ee8c1f6cb4821 --- /dev/null +++ b/src/test/ui/drop/repeat-drop-2.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/repeat-drop-2.rs:4:17 + | +LL | let foo = String::new(); + | --- move occurs because `foo` has type `String`, which does not implement the `Copy` trait +LL | let _bar = foo; + | --- value moved here +LL | let _baz = [foo; 0]; + | ^^^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/drop/repeat-drop.rs b/src/test/ui/drop/repeat-drop.rs new file mode 100644 index 0000000000000..90c43d1e136cf --- /dev/null +++ b/src/test/ui/drop/repeat-drop.rs @@ -0,0 +1,36 @@ +// run-pass + +static mut COUNT: usize = 0; + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + unsafe { + COUNT += 1; + } + } +} + +fn a() { + let foo = Foo; + let v: [Foo; 0] = [foo; 0]; + unsafe { assert_eq!(COUNT, 1) } + std::mem::drop(v); +} + +fn b() { + let foo = Foo; + let v: [Foo; 1] = [foo; 1]; + unsafe { assert_eq!(COUNT, 0) } + std::mem::drop(v); + unsafe { assert_eq!(COUNT, 1) } +} + +fn main() { + a(); + unsafe { + COUNT = 0; + } + b(); +}