impl Copy/Clone for arrays in std, not in compiler
This commit is contained in:
parent
495322d776
commit
ce1143e94d
9 changed files with 30 additions and 187 deletions
|
@ -310,7 +310,6 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
|
||||||
|
|
||||||
match self_ty.kind() {
|
match self_ty.kind() {
|
||||||
_ if is_copy => builder.copy_shim(),
|
_ if is_copy => builder.copy_shim(),
|
||||||
ty::Array(ty, len) => builder.array_shim(dest, src, ty, len),
|
|
||||||
ty::Closure(_, substs) => {
|
ty::Closure(_, substs) => {
|
||||||
builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys())
|
builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys())
|
||||||
}
|
}
|
||||||
|
@ -459,154 +458,6 @@ impl CloneShimBuilder<'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loop_header(
|
|
||||||
&mut self,
|
|
||||||
beg: Place<'tcx>,
|
|
||||||
end: Place<'tcx>,
|
|
||||||
loop_body: BasicBlock,
|
|
||||||
loop_end: BasicBlock,
|
|
||||||
is_cleanup: bool,
|
|
||||||
) {
|
|
||||||
let tcx = self.tcx;
|
|
||||||
|
|
||||||
let cond = self.make_place(Mutability::Mut, tcx.types.bool);
|
|
||||||
let compute_cond = self.make_statement(StatementKind::Assign(Box::new((
|
|
||||||
cond,
|
|
||||||
Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Copy(end), Operand::Copy(beg)))),
|
|
||||||
))));
|
|
||||||
|
|
||||||
// `if end != beg { goto loop_body; } else { goto loop_end; }`
|
|
||||||
self.block(
|
|
||||||
vec![compute_cond],
|
|
||||||
TerminatorKind::if_(tcx, Operand::Move(cond), loop_body, loop_end),
|
|
||||||
is_cleanup,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
|
|
||||||
Box::new(Constant {
|
|
||||||
span: self.span,
|
|
||||||
user_ty: None,
|
|
||||||
literal: ty::Const::from_usize(self.tcx, value).into(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn array_shim(
|
|
||||||
&mut self,
|
|
||||||
dest: Place<'tcx>,
|
|
||||||
src: Place<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
len: &'tcx ty::Const<'tcx>,
|
|
||||||
) {
|
|
||||||
let tcx = self.tcx;
|
|
||||||
let span = self.span;
|
|
||||||
|
|
||||||
let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span));
|
|
||||||
let end = self.make_place(Mutability::Not, tcx.types.usize);
|
|
||||||
|
|
||||||
// BB #0
|
|
||||||
// `let mut beg = 0;`
|
|
||||||
// `let end = len;`
|
|
||||||
// `goto #1;`
|
|
||||||
let inits = vec![
|
|
||||||
self.make_statement(StatementKind::Assign(Box::new((
|
|
||||||
Place::from(beg),
|
|
||||||
Rvalue::Use(Operand::Constant(self.make_usize(0))),
|
|
||||||
)))),
|
|
||||||
self.make_statement(StatementKind::Assign(Box::new((
|
|
||||||
end,
|
|
||||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
|
||||||
span: self.span,
|
|
||||||
user_ty: None,
|
|
||||||
literal: len.into(),
|
|
||||||
}))),
|
|
||||||
)))),
|
|
||||||
];
|
|
||||||
self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false);
|
|
||||||
|
|
||||||
// BB #1: loop {
|
|
||||||
// BB #2;
|
|
||||||
// BB #3;
|
|
||||||
// }
|
|
||||||
// BB #4;
|
|
||||||
self.loop_header(Place::from(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
|
|
||||||
|
|
||||||
// BB #2
|
|
||||||
// `dest[i] = Clone::clone(src[beg])`;
|
|
||||||
// Goto #3 if ok, #5 if unwinding happens.
|
|
||||||
let dest_field = self.tcx.mk_place_index(dest, beg);
|
|
||||||
let src_field = self.tcx.mk_place_index(src, beg);
|
|
||||||
self.make_clone_call(dest_field, src_field, ty, BasicBlock::new(3), BasicBlock::new(5));
|
|
||||||
|
|
||||||
// BB #3
|
|
||||||
// `beg = beg + 1;`
|
|
||||||
// `goto #1`;
|
|
||||||
let statements = vec![self.make_statement(StatementKind::Assign(Box::new((
|
|
||||||
Place::from(beg),
|
|
||||||
Rvalue::BinaryOp(
|
|
||||||
BinOp::Add,
|
|
||||||
Box::new((Operand::Copy(Place::from(beg)), Operand::Constant(self.make_usize(1)))),
|
|
||||||
),
|
|
||||||
))))];
|
|
||||||
self.block(statements, TerminatorKind::Goto { target: BasicBlock::new(1) }, false);
|
|
||||||
|
|
||||||
// BB #4
|
|
||||||
// `return dest;`
|
|
||||||
self.block(vec![], TerminatorKind::Return, false);
|
|
||||||
|
|
||||||
// BB #5 (cleanup)
|
|
||||||
// `let end = beg;`
|
|
||||||
// `let mut beg = 0;`
|
|
||||||
// goto #6;
|
|
||||||
let end = beg;
|
|
||||||
let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span));
|
|
||||||
let init = self.make_statement(StatementKind::Assign(Box::new((
|
|
||||||
Place::from(beg),
|
|
||||||
Rvalue::Use(Operand::Constant(self.make_usize(0))),
|
|
||||||
))));
|
|
||||||
self.block(vec![init], TerminatorKind::Goto { target: BasicBlock::new(6) }, true);
|
|
||||||
|
|
||||||
// BB #6 (cleanup): loop {
|
|
||||||
// BB #7;
|
|
||||||
// BB #8;
|
|
||||||
// }
|
|
||||||
// BB #9;
|
|
||||||
self.loop_header(
|
|
||||||
Place::from(beg),
|
|
||||||
Place::from(end),
|
|
||||||
BasicBlock::new(7),
|
|
||||||
BasicBlock::new(9),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
// BB #7 (cleanup)
|
|
||||||
// `drop(dest[beg])`;
|
|
||||||
self.block(
|
|
||||||
vec![],
|
|
||||||
TerminatorKind::Drop {
|
|
||||||
place: self.tcx.mk_place_index(dest, beg),
|
|
||||||
target: BasicBlock::new(8),
|
|
||||||
unwind: None,
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
// BB #8 (cleanup)
|
|
||||||
// `beg = beg + 1;`
|
|
||||||
// `goto #6;`
|
|
||||||
let statement = self.make_statement(StatementKind::Assign(Box::new((
|
|
||||||
Place::from(beg),
|
|
||||||
Rvalue::BinaryOp(
|
|
||||||
BinOp::Add,
|
|
||||||
Box::new((Operand::Copy(Place::from(beg)), Operand::Constant(self.make_usize(1)))),
|
|
||||||
),
|
|
||||||
))));
|
|
||||||
self.block(vec![statement], TerminatorKind::Goto { target: BasicBlock::new(6) }, true);
|
|
||||||
|
|
||||||
// BB #9 (resume)
|
|
||||||
self.block(vec![], TerminatorKind::Resume, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tuple_like_shim<I>(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I)
|
fn tuple_like_shim<I>(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I)
|
||||||
where
|
where
|
||||||
I: Iterator<Item = Ty<'tcx>>,
|
I: Iterator<Item = Ty<'tcx>>,
|
||||||
|
|
|
@ -33,7 +33,8 @@ pub fn can_type_implement_copy(
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::RawPtr(..)
|
| ty::RawPtr(..)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
|
| ty::Ref(_, _, hir::Mutability::Not)
|
||||||
|
| ty::Array(..) => return Ok(()),
|
||||||
|
|
||||||
ty::Adt(adt, substs) => (adt, substs),
|
ty::Adt(adt, substs) => (adt, substs),
|
||||||
|
|
||||||
|
|
|
@ -1859,7 +1859,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::RawPtr(..)
|
| ty::RawPtr(..)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Ref(_, _, hir::Mutability::Not) => {
|
| ty::Ref(_, _, hir::Mutability::Not)
|
||||||
|
| ty::Array(..) => {
|
||||||
// Implementations provided in libcore
|
// Implementations provided in libcore
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1872,11 +1873,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
| ty::Foreign(..)
|
| ty::Foreign(..)
|
||||||
| ty::Ref(_, _, hir::Mutability::Mut) => None,
|
| ty::Ref(_, _, hir::Mutability::Mut) => None,
|
||||||
|
|
||||||
ty::Array(element_ty, _) => {
|
|
||||||
// (*) binder moved here
|
|
||||||
Where(obligation.predicate.rebind(vec![element_ty]))
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Tuple(tys) => {
|
ty::Tuple(tys) => {
|
||||||
// (*) binder moved here
|
// (*) binder moved here
|
||||||
Where(obligation.predicate.rebind(tys.iter().map(|k| k.expect_ty()).collect()))
|
Where(obligation.predicate.rebind(tys.iter().map(|k| k.expect_ty()).collect()))
|
||||||
|
|
|
@ -362,7 +362,7 @@ fn resolve_associated_item<'tcx>(
|
||||||
let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env);
|
let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env);
|
||||||
match self_ty.kind() {
|
match self_ty.kind() {
|
||||||
_ if is_copy => (),
|
_ if is_copy => (),
|
||||||
ty::Array(..) | ty::Closure(..) | ty::Tuple(..) => {}
|
ty::Closure(..) | ty::Tuple(..) => {}
|
||||||
_ => return Ok(None),
|
_ => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,24 @@ impl<T: Ord, const N: usize> Ord for [T; N] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[stable(feature = "copy_clone_array_lib", since = "1.55.0")]
|
||||||
|
impl<T: Copy, const N: usize> Copy for [T; N] {}
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[stable(feature = "copy_clone_array_lib", since = "1.55.0")]
|
||||||
|
impl<T: Clone, const N: usize> Clone for [T; N] {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
// SAFETY: we know for certain that this iterator will yield exactly `N`
|
||||||
|
// items.
|
||||||
|
unsafe { collect_into_array_unchecked(&mut self.iter().cloned()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_from(&mut self, other: &Self) {
|
||||||
|
self.clone_from_slice(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The Default impls cannot be done with const generics because `[T; 0]` doesn't
|
// The Default impls cannot be done with const generics because `[T; 0]` doesn't
|
||||||
// require Default to be implemented, and having different impl blocks for
|
// require Default to be implemented, and having different impl blocks for
|
||||||
// different numbers isn't supported yet.
|
// different numbers isn't supported yet.
|
||||||
|
|
|
@ -53,7 +53,7 @@ fn main() {
|
||||||
].clone();
|
].clone();
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(result.is_err());
|
assert!(child.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1,
|
1,
|
||||||
Rc::strong_count(&counter)
|
Rc::strong_count(&counter)
|
||||||
|
|
|
@ -23,11 +23,12 @@ fn test_copy_clone<T: Copy + Clone>(arg: T) {
|
||||||
fn foo() { }
|
fn foo() { }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// FIXME: add closures when they're considered WF
|
||||||
test_copy_clone(foo);
|
test_copy_clone(foo);
|
||||||
let f: fn() = foo;
|
let f: fn() = foo;
|
||||||
test_copy_clone(f);
|
test_copy_clone(f);
|
||||||
// FIXME: add closures when they're considered WF
|
// FIXME(#86252): reinstate array test after chalk upgrade
|
||||||
test_copy_clone([1; 56]);
|
//test_copy_clone([1; 56]);
|
||||||
test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
|
test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
|
||||||
test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1));
|
test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1));
|
||||||
test_copy_clone(());
|
test_copy_clone(());
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
type Foo = [u8; 256];
|
|
||||||
|
|
||||||
impl Copy for Foo { }
|
|
||||||
//~^ ERROR the trait `Copy` may not be implemented for this type
|
|
||||||
//~| ERROR only traits defined in the current crate can be implemented for arbitrary types
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Bar;
|
struct Bar;
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,9 @@
|
||||||
error[E0206]: the trait `Copy` may not be implemented for this type
|
error[E0206]: the trait `Copy` may not be implemented for this type
|
||||||
--> $DIR/E0206.rs:3:15
|
--> $DIR/E0206.rs:4:15
|
||||||
|
|
|
||||||
LL | impl Copy for Foo { }
|
|
||||||
| ^^^ type is not a structure or enumeration
|
|
||||||
|
|
||||||
error[E0206]: the trait `Copy` may not be implemented for this type
|
|
||||||
--> $DIR/E0206.rs:10:15
|
|
||||||
|
|
|
|
||||||
LL | impl Copy for &'static mut Bar { }
|
LL | impl Copy for &'static mut Bar { }
|
||||||
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
|
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
|
||||||
|
|
||||||
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
error: aborting due to previous error
|
||||||
--> $DIR/E0206.rs:3:1
|
|
||||||
|
|
|
||||||
LL | impl Copy for Foo { }
|
|
||||||
| ^^^^^^^^^^^^^^---
|
|
||||||
| | |
|
|
||||||
| | this is not defined in the current crate because arrays are always foreign
|
|
||||||
| impl doesn't use only types from inside the current crate
|
|
||||||
|
|
|
||||||
= note: define and implement a trait or new type instead
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
For more information about this error, try `rustc --explain E0206`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0117, E0206.
|
|
||||||
For more information about an error, try `rustc --explain E0117`.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue