diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6dcdd46816e..c4a190b44cb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -37,18 +37,13 @@ use rustc_middle::ty::{ use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::VariantIdx; -use rustc_trait_selection::infer::InferCtxtExt as _; -use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::query::type_op; use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use rustc_trait_selection::traits::query::Fallible; -use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation}; +use rustc_trait_selection::traits::PredicateObligation; -use rustc_const_eval::transform::{ - check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression, -}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; @@ -1868,41 +1863,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Operand::Move(place) => { // 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); - let is_const_fn = - is_const_fn_in_array_repeat_expression(&ccx, &place, &body); + let ty = place.ty(body, tcx).ty; + let trait_ref = ty::TraitRef::new( + tcx.require_lang_item(LangItem::Copy, Some(span)), + tcx.mk_substs_trait(ty, &[]), + ); - debug!("check_rvalue: is_const_fn={:?}", is_const_fn); - - let def_id = body.source.def_id().expect_local(); - let obligation = traits::Obligation::new( - ObligationCause::new( - span, - self.tcx().hir().local_def_id_to_hir_id(def_id), - traits::ObligationCauseCode::RepeatElementCopy { - is_const_fn, - }, - ), - self.param_env, - ty::Binder::dummy(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()), - ); - self.infcx.report_selection_error( - obligation.clone(), - &obligation, - &traits::SelectionError::Unimplemented, - false, - ); - } + self.prove_trait_ref( + trait_ref, + Locations::Single(location), + ConstraintCategory::CopyBound, + ); } } } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 47cb1ea48cb..7111bbaa3cd 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1292,6 +1292,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return tcx.ty_error(); } + let is_const = match &element.kind { + hir::ExprKind::ConstBlock(..) => true, + hir::ExprKind::Path(qpath) => { + let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id); + matches!( + res, + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) + ) + } + _ => false, + }; + + if !is_const { + let is_const_fn = match element.kind { + hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() { + ty::FnDef(def_id, _) => tcx.is_const_fn(def_id), + _ => false, + }, + _ => false, + }; + + if count.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) { + let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); + let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn }; + self.require_type_meets(element_ty, element.span, code, lang_item); + } + } + tcx.mk_ty(ty::Array(t, count)) } diff --git a/src/test/ui/array-slice-vec/repeat_empty_ok.stderr b/src/test/ui/array-slice-vec/repeat_empty_ok.stderr index eba1a8e2278..cf5efdaab2a 100644 --- a/src/test/ui/array-slice-vec/repeat_empty_ok.stderr +++ b/src/test/ui/array-slice-vec/repeat_empty_ok.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied - --> $DIR/repeat_empty_ok.rs:8:19 + --> $DIR/repeat_empty_ok.rs:8:20 | LL | let headers = [Header{value: &[]}; 128]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because the repeated element will be copied help: consider annotating `Header<'_>` with `#[derive(Copy)]` @@ -11,10 +11,10 @@ LL | #[derive(Copy)] | error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied - --> $DIR/repeat_empty_ok.rs:13:19 + --> $DIR/repeat_empty_ok.rs:13:20 | LL | let headers = [Header{value: &[0]}; 128]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because the repeated element will be copied help: consider annotating `Header<'_>` with `#[derive(Copy)]` diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr index 48aaaf5e544..ccc42f08acf 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-61336-2.rs:6:5 + --> $DIR/issue-61336-2.rs:6:6 | LL | [x; { N }] - | ^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^ the trait `Copy` is not implemented for `T` | = note: the `Copy` trait is required because the repeated element will be copied help: consider restricting type parameter `T` diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr index 665a1a677a1..a6a7fee0007 100644 --- a/src/test/ui/const-generics/issues/issue-61336.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-61336.rs:6:5 + --> $DIR/issue-61336.rs:6:6 | LL | [x; N] - | ^^^^^^ the trait `Copy` is not implemented for `T` + | ^ the trait `Copy` is not implemented for `T` | = note: the `Copy` trait is required because the repeated element will be copied help: consider restricting type parameter `T` diff --git a/src/test/ui/consts/const-blocks/fn-call-in-non-const.rs b/src/test/ui/consts/const-blocks/fn-call-in-non-const.rs index 19217843759..18b4dc714de 100644 --- a/src/test/ui/consts/const-blocks/fn-call-in-non-const.rs +++ b/src/test/ui/consts/const-blocks/fn-call-in-non-const.rs @@ -12,5 +12,5 @@ const fn copy() -> u32 { fn main() { let _: [u32; 2] = [copy(); 2]; let _: [Option; 2] = [no_copy(); 2]; - //~^ ERROR the trait bound `Option: Copy` is not satisfied + //~^ ERROR the trait bound `Bar: Copy` is not satisfied } diff --git a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr index 52a1669e330..ef05f723aca 100644 --- a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -1,13 +1,17 @@ -error[E0277]: the trait bound `Option: Copy` is not satisfied - --> $DIR/fn-call-in-non-const.rs:14:31 +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/fn-call-in-non-const.rs:14:32 | LL | let _: [Option; 2] = [no_copy(); 2]; - | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Option` + | ^^^^^^^^^ the trait `Copy` is not implemented for `Bar` | - = help: the trait `Copy` is implemented for `Option` + = note: required because of the requirements on the impl of `Copy` for `Option` = note: the `Copy` trait is required because the repeated element will be copied = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to previous error diff --git a/src/test/ui/consts/const-blocks/migrate-fail.rs b/src/test/ui/consts/const-blocks/migrate-fail.rs index bb12139a7ba..d5a17249cc9 100644 --- a/src/test/ui/consts/const-blocks/migrate-fail.rs +++ b/src/test/ui/consts/const-blocks/migrate-fail.rs @@ -11,13 +11,13 @@ mod non_constants { fn no_impl_copy_empty_value_multiple_elements() { let x = None; let arr: [Option; 2] = [x; 2]; - //~^ ERROR the trait bound `Option: Copy` is not satisfied [E0277] + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] } fn no_impl_copy_value_multiple_elements() { let x = Some(Bar); let arr: [Option; 2] = [x; 2]; - //~^ ERROR the trait bound `Option: Copy` is not satisfied [E0277] + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] } } diff --git a/src/test/ui/consts/const-blocks/migrate-fail.stderr b/src/test/ui/consts/const-blocks/migrate-fail.stderr index 318fec60290..1898ab3b469 100644 --- a/src/test/ui/consts/const-blocks/migrate-fail.stderr +++ b/src/test/ui/consts/const-blocks/migrate-fail.stderr @@ -1,20 +1,28 @@ -error[E0277]: the trait bound `Option: Copy` is not satisfied - --> $DIR/migrate-fail.rs:13:37 +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/migrate-fail.rs:13:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^^^^^^ the trait `Copy` is not implemented for `Option` + | ^ the trait `Copy` is not implemented for `Bar` | - = help: the trait `Copy` is implemented for `Option` + = note: required because of the requirements on the impl of `Copy` for `Option` = note: the `Copy` trait is required because the repeated element will be copied +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | -error[E0277]: the trait bound `Option: Copy` is not satisfied - --> $DIR/migrate-fail.rs:19:37 +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/migrate-fail.rs:19:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^^^^^^ the trait `Copy` is not implemented for `Option` + | ^ the trait `Copy` is not implemented for `Bar` | - = help: the trait `Copy` is implemented for `Option` + = note: required because of the requirements on the impl of `Copy` for `Option` = note: the `Copy` trait is required because the repeated element will be copied +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-blocks/nll-fail.rs b/src/test/ui/consts/const-blocks/nll-fail.rs index 871387c1fd0..9d4aef39e54 100644 --- a/src/test/ui/consts/const-blocks/nll-fail.rs +++ b/src/test/ui/consts/const-blocks/nll-fail.rs @@ -10,13 +10,13 @@ mod non_constants { fn no_impl_copy_empty_value_multiple_elements() { let x = None; let arr: [Option; 2] = [x; 2]; - //~^ ERROR the trait bound `Option: Copy` is not satisfied [E0277] + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] } fn no_impl_copy_value_multiple_elements() { let x = Some(Bar); let arr: [Option; 2] = [x; 2]; - //~^ ERROR the trait bound `Option: Copy` is not satisfied [E0277] + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] } } diff --git a/src/test/ui/consts/const-blocks/nll-fail.stderr b/src/test/ui/consts/const-blocks/nll-fail.stderr index 5a34361aa83..3201a1e68e8 100644 --- a/src/test/ui/consts/const-blocks/nll-fail.stderr +++ b/src/test/ui/consts/const-blocks/nll-fail.stderr @@ -1,20 +1,28 @@ -error[E0277]: the trait bound `Option: Copy` is not satisfied - --> $DIR/nll-fail.rs:12:37 +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/nll-fail.rs:12:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^^^^^^ the trait `Copy` is not implemented for `Option` + | ^ the trait `Copy` is not implemented for `Bar` | - = help: the trait `Copy` is implemented for `Option` + = note: required because of the requirements on the impl of `Copy` for `Option` = note: the `Copy` trait is required because the repeated element will be copied +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | -error[E0277]: the trait bound `Option: Copy` is not satisfied - --> $DIR/nll-fail.rs:18:37 +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/nll-fail.rs:18:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^^^^^^ the trait `Copy` is not implemented for `Option` + | ^ the trait `Copy` is not implemented for `Bar` | - = help: the trait `Copy` is implemented for `Option` + = note: required because of the requirements on the impl of `Copy` for `Option` = note: the `Copy` trait is required because the repeated element will be copied +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-blocks/trait-error.rs b/src/test/ui/consts/const-blocks/trait-error.rs index 5a614cbdd15..49d1e9b9434 100644 --- a/src/test/ui/consts/const-blocks/trait-error.rs +++ b/src/test/ui/consts/const-blocks/trait-error.rs @@ -3,5 +3,5 @@ struct Foo(T); fn main() { [Foo(String::new()); 4]; - //~^ ERROR the trait bound `Foo: Copy` is not satisfied [E0277] + //~^ ERROR the trait bound `String: Copy` is not satisfied [E0277] } diff --git a/src/test/ui/consts/const-blocks/trait-error.stderr b/src/test/ui/consts/const-blocks/trait-error.stderr index 6979ff36176..8a6ca61e0c5 100644 --- a/src/test/ui/consts/const-blocks/trait-error.stderr +++ b/src/test/ui/consts/const-blocks/trait-error.stderr @@ -1,11 +1,18 @@ -error[E0277]: the trait bound `Foo: Copy` is not satisfied - --> $DIR/trait-error.rs:5:5 +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/trait-error.rs:5:6 | LL | [Foo(String::new()); 4]; - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | - = help: the trait `Copy` is implemented for `Foo` +note: required because of the requirements on the impl of `Copy` for `Foo` + --> $DIR/trait-error.rs:1:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ = note: the `Copy` trait is required because the repeated element will be copied + = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` + = help: create an inline `const` block, see RFC #2920 for more information + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/consts/const-fn-in-vec.stderr b/src/test/ui/consts/const-fn-in-vec.stderr index f02cb4f1ff1..0572dda7470 100644 --- a/src/test/ui/consts/const-fn-in-vec.stderr +++ b/src/test/ui/consts/const-fn-in-vec.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/const-fn-in-vec.rs:4:32 + --> $DIR/const-fn-in-vec.rs:4:33 | LL | let strings: [String; 5] = [String::new(); 5]; - | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | = note: the `Copy` trait is required because the repeated element will be copied = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` diff --git a/src/test/ui/lifetimes/copy_modulo_regions.rs b/src/test/ui/lifetimes/copy_modulo_regions.rs new file mode 100644 index 00000000000..1d5d90ffcb4 --- /dev/null +++ b/src/test/ui/lifetimes/copy_modulo_regions.rs @@ -0,0 +1,19 @@ +#![feature(nll)] + +#[derive(Clone)] +struct Foo<'a>(fn(&'a ()) -> &'a ()); + +impl Copy for Foo<'static> {} + +fn mk_foo<'a>() -> Foo<'a> { + println!("mk_foo"); + Foo(|x| x) +} + +fn foo<'a>() -> [Foo<'a>; 100] { + [mk_foo::<'a>(); 100] //~ ERROR lifetime may not live long enough +} + +fn main() { + foo(); +} diff --git a/src/test/ui/lifetimes/copy_modulo_regions.stderr b/src/test/ui/lifetimes/copy_modulo_regions.stderr new file mode 100644 index 00000000000..e027bc45426 --- /dev/null +++ b/src/test/ui/lifetimes/copy_modulo_regions.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/copy_modulo_regions.rs:14:5 + | +LL | fn foo<'a>() -> [Foo<'a>; 100] { + | -- lifetime `'a` defined here +LL | [mk_foo::<'a>(); 100] + | ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/src/test/ui/repeat-to-run-dtor-twice.stderr b/src/test/ui/repeat-to-run-dtor-twice.stderr index 904413712cd..fd64ce8bcea 100644 --- a/src/test/ui/repeat-to-run-dtor-twice.stderr +++ b/src/test/ui/repeat-to-run-dtor-twice.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied - --> $DIR/repeat-to-run-dtor-twice.rs:17:13 + --> $DIR/repeat-to-run-dtor-twice.rs:17:15 | LL | let _ = [ a; 5 ]; - | ^^^^^^^^ the trait `Copy` is not implemented for `Foo` + | ^ the trait `Copy` is not implemented for `Foo` | = note: the `Copy` trait is required because the repeated element will be copied help: consider annotating `Foo` with `#[derive(Copy)]`