From 54a3ed3114c5fcacfa9ec15e89935c105b4c00a9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 21 Nov 2020 17:42:03 +0100 Subject: [PATCH 1/3] use exhaustive match for checking Rvalue::Repeat --- .../src/borrow_check/type_check/mod.rs | 78 ++++++++++--------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 543b7e7ebaa79..42cd050abc5dd 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1988,44 +1988,48 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // If the length is larger than 1, the repeat expression will need to copy the // element, so we require the `Copy` trait. if len.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) { - if let Operand::Move(_) = operand { - // While this is located in `nll::typeck` this error is not an NLL error, it's - // a required check to make sure that repeated elements implement `Copy`. - let span = body.source_info(location).span; - let ty = operand.ty(body, tcx); - if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) { - let ccx = ConstCx::new_with_param_env(tcx, body, self.param_env); - // To determine if `const_in_array_repeat_expressions` feature gate should - // be mentioned, need to check if the rvalue is promotable. - let should_suggest = - should_suggest_const_in_array_repeat_expressions_attribute( - &ccx, operand, - ); - debug!("check_rvalue: should_suggest={:?}", should_suggest); - - let def_id = body.source.def_id().expect_local(); - self.infcx.report_selection_error( - &traits::Obligation::new( - ObligationCause::new( - span, - self.tcx().hir().local_def_id_to_hir_id(def_id), - traits::ObligationCauseCode::RepeatVec(should_suggest), - ), - self.param_env, - ty::Binder::bind(ty::TraitRef::new( - self.tcx().require_lang_item( - LangItem::Copy, - Some(self.last_span), + match operand { + Operand::Copy(..) | Operand::Constant(..) => { + // These are always okay: direct use of a const, or a value that can evidently be copied. + } + Operand::Move(_) => { + // Make sure that repeated elements implement `Copy`. + let span = body.source_info(location).span; + let ty = operand.ty(body, tcx); + if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) { + let ccx = ConstCx::new_with_param_env(tcx, body, self.param_env); + // To determine if `const_in_array_repeat_expressions` feature gate should + // be mentioned, need to check if the rvalue is promotable. + let should_suggest = + should_suggest_const_in_array_repeat_expressions_attribute( + &ccx, operand, + ); + debug!("check_rvalue: should_suggest={:?}", should_suggest); + + let def_id = body.source.def_id().expect_local(); + self.infcx.report_selection_error( + &traits::Obligation::new( + ObligationCause::new( + span, + self.tcx().hir().local_def_id_to_hir_id(def_id), + traits::ObligationCauseCode::RepeatVec(should_suggest), ), - tcx.mk_substs_trait(ty, &[]), - )) - .without_const() - .to_predicate(self.tcx()), - ), - &traits::SelectionError::Unimplemented, - false, - false, - ); + self.param_env, + ty::Binder::bind(ty::TraitRef::new( + self.tcx().require_lang_item( + LangItem::Copy, + Some(self.last_span), + ), + tcx.mk_substs_trait(ty, &[]), + )) + .without_const() + .to_predicate(self.tcx()), + ), + &traits::SelectionError::Unimplemented, + false, + false, + ); + } } } } From f8d4883dbebf71348abe1134c6f26d48a36256b9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 21 Nov 2020 18:05:29 +0100 Subject: [PATCH 2/3] add test that repeating non-Copy constants works --- .../const-repeat.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs diff --git a/src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs b/src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs new file mode 100644 index 0000000000000..11611a949187b --- /dev/null +++ b/src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs @@ -0,0 +1,13 @@ +// check-pass + +// Repeating a *constant* of non-Copy type (not just a constant expression) is already stable. + +const EMPTY: Vec = Vec::new(); + +pub fn bar() -> [Vec; 2] { + [EMPTY; 2] +} + +fn main() { + let x = bar(); +} From 7f3e18cc2b24214e10df5434972f4f7cd461fa98 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 28 Nov 2020 17:32:48 +0100 Subject: [PATCH 3/3] make sure [CONST; N] drops N times --- .../const-repeat.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs b/src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs index 11611a949187b..65d02317d34c5 100644 --- a/src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs +++ b/src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-repeat.rs @@ -1,4 +1,4 @@ -// check-pass +// run-pass // Repeating a *constant* of non-Copy type (not just a constant expression) is already stable. @@ -8,6 +8,20 @@ pub fn bar() -> [Vec; 2] { [EMPTY; 2] } +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + panic!("BOOM!"); + } +} + +const BOOM: Bomb = Bomb; + fn main() { - let x = bar(); + let _x = bar(); + + // Make sure the destructor does not get called for empty arrays. `[CONST; N]` should + // instantiate (and then later drop) the const exactly `N` times. + let _x = [BOOM; 0]; }