mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Check that repeat expression elements are Copy (ignoring lifetimes) in typeck and that they are Copy (with proper lifetime checks) in borrowck
This commit is contained in:
parent
0e7915d11f
commit
4e6e68e27a
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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)]`
|
||||
|
@ -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`
|
||||
|
@ -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`
|
||||
|
@ -12,5 +12,5 @@ const fn copy() -> u32 {
|
||||
fn main() {
|
||||
let _: [u32; 2] = [copy(); 2];
|
||||
let _: [Option<Bar>; 2] = [no_copy(); 2];
|
||||
//~^ ERROR the trait bound `Option<Bar>: Copy` is not satisfied
|
||||
//~^ ERROR the trait bound `Bar: Copy` is not satisfied
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
error[E0277]: the trait bound `Option<Bar>: 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<Bar>; 2] = [no_copy(); 2];
|
||||
| ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Option<Bar>`
|
||||
| ^^^^^^^^^ the trait `Copy` is not implemented for `Bar`
|
||||
|
|
||||
= help: the trait `Copy` is implemented for `Option<T>`
|
||||
= note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
|
||||
= 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 <https://github.com/rust-lang/rfcs/pull/2920> for more information
|
||||
help: consider annotating `Bar` with `#[derive(Copy)]`
|
||||
|
|
||||
LL | #[derive(Copy)]
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -11,13 +11,13 @@ mod non_constants {
|
||||
fn no_impl_copy_empty_value_multiple_elements() {
|
||||
let x = None;
|
||||
let arr: [Option<Bar>; 2] = [x; 2];
|
||||
//~^ ERROR the trait bound `Option<Bar>: 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<Bar>; 2] = [x; 2];
|
||||
//~^ ERROR the trait bound `Option<Bar>: Copy` is not satisfied [E0277]
|
||||
//~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,28 @@
|
||||
error[E0277]: the trait bound `Option<Bar>: 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<Bar>; 2] = [x; 2];
|
||||
| ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>`
|
||||
| ^ the trait `Copy` is not implemented for `Bar`
|
||||
|
|
||||
= help: the trait `Copy` is implemented for `Option<T>`
|
||||
= note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
|
||||
= 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<Bar>: 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<Bar>; 2] = [x; 2];
|
||||
| ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>`
|
||||
| ^ the trait `Copy` is not implemented for `Bar`
|
||||
|
|
||||
= help: the trait `Copy` is implemented for `Option<T>`
|
||||
= note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
|
||||
= 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
|
||||
|
||||
|
@ -10,13 +10,13 @@ mod non_constants {
|
||||
fn no_impl_copy_empty_value_multiple_elements() {
|
||||
let x = None;
|
||||
let arr: [Option<Bar>; 2] = [x; 2];
|
||||
//~^ ERROR the trait bound `Option<Bar>: 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<Bar>; 2] = [x; 2];
|
||||
//~^ ERROR the trait bound `Option<Bar>: Copy` is not satisfied [E0277]
|
||||
//~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,28 @@
|
||||
error[E0277]: the trait bound `Option<Bar>: 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<Bar>; 2] = [x; 2];
|
||||
| ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>`
|
||||
| ^ the trait `Copy` is not implemented for `Bar`
|
||||
|
|
||||
= help: the trait `Copy` is implemented for `Option<T>`
|
||||
= note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
|
||||
= 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<Bar>: 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<Bar>; 2] = [x; 2];
|
||||
| ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>`
|
||||
| ^ the trait `Copy` is not implemented for `Bar`
|
||||
|
|
||||
= help: the trait `Copy` is implemented for `Option<T>`
|
||||
= note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
|
||||
= 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
|
||||
|
||||
|
@ -3,5 +3,5 @@ struct Foo<T>(T);
|
||||
|
||||
fn main() {
|
||||
[Foo(String::new()); 4];
|
||||
//~^ ERROR the trait bound `Foo<String>: Copy` is not satisfied [E0277]
|
||||
//~^ ERROR the trait bound `String: Copy` is not satisfied [E0277]
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
error[E0277]: the trait bound `Foo<String>: 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<String>`
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
= help: the trait `Copy` is implemented for `Foo<T>`
|
||||
note: required because of the requirements on the impl of `Copy` for `Foo<String>`
|
||||
--> $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 <https://github.com/rust-lang/rfcs/pull/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
|
||||
|
||||
|
@ -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];`
|
||||
|
19
src/test/ui/lifetimes/copy_modulo_regions.rs
Normal file
19
src/test/ui/lifetimes/copy_modulo_regions.rs
Normal file
@ -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();
|
||||
}
|
14
src/test/ui/lifetimes/copy_modulo_regions.stderr
Normal file
14
src/test/ui/lifetimes/copy_modulo_regions.stderr
Normal file
@ -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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -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)]`
|
||||
|
Loading…
Reference in New Issue
Block a user