Skip to content

Commit b5a54d8

Browse files
committed
Move is_trivially_pure_clone_copy onto Ty instead
1 parent 0d4a3f1 commit b5a54d8

File tree

2 files changed

+53
-12
lines changed

2 files changed

+53
-12
lines changed

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,6 +2371,57 @@ impl<'tcx> Ty<'tcx> {
23712371
}
23722372
}
23732373
}
2374+
2375+
/// Fast path helper for primitives which are always `Copy` and which
2376+
/// have a side-effect-free `Clone` impl.
2377+
///
2378+
/// Returning true means the type is known to be pure and `Copy+Clone`.
2379+
/// Returning `false` means nothing -- could be `Copy`, might not be.
2380+
///
2381+
/// This is mostly useful for optimizations, as there are the types
2382+
/// on which we can replace cloning with dereferencing.
2383+
pub fn is_trivially_pure_clone_copy(self) -> bool {
2384+
match self.kind() {
2385+
ty::Bool | ty::Char | ty::Never => true,
2386+
2387+
// These aren't even `Clone`
2388+
ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false,
2389+
2390+
ty::Int(..) | ty::Uint(..) | ty::Float(..) => true,
2391+
2392+
// The voldemort ZSTs are fine.
2393+
ty::FnDef(..) => true,
2394+
2395+
ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(),
2396+
2397+
// A 100-tuple isn't "trivial", so doing this only for reasonable sizes.
2398+
ty::Tuple(field_tys) => {
2399+
field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy)
2400+
}
2401+
2402+
// Sometimes traits aren't implemented for every ABI or arity,
2403+
// because we can't be generic over everything yet.
2404+
ty::FnPtr(..) => false,
2405+
2406+
// Definitely absolutely not copy.
2407+
ty::Ref(_, _, hir::Mutability::Mut) => false,
2408+
2409+
// Thin pointers & thin shared references are pure-clone-copy, but for
2410+
// anything with custom metadata it might be more complicated.
2411+
ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false,
2412+
2413+
ty::Generator(..) | ty::GeneratorWitness(..) => false,
2414+
2415+
// Might be, but not "trivial" so just giving the safe answer.
2416+
ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false,
2417+
2418+
ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
2419+
2420+
ty::Bound(..) | ty::Placeholder(..) => {
2421+
bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
2422+
}
2423+
}
2424+
}
23742425
}
23752426

23762427
/// Extra information about why we ended up with a particular variance.

compiler/rustc_mir_transform/src/instcombine.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_middle::mir::{
66
BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
77
Statement, StatementKind, Terminator, TerminatorKind, UnOp,
88
};
9-
use rustc_middle::ty::{self, Ty, TyCtxt, TyKind};
9+
use rustc_middle::ty::{self, TyCtxt};
1010

1111
pub struct InstCombine;
1212

@@ -168,7 +168,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
168168
let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind()
169169
else { return };
170170

171-
if !is_trivially_pure_copy(self.tcx, inner_ty) {
171+
if !inner_ty.is_trivially_pure_clone_copy() {
172172
return;
173173
}
174174

@@ -202,13 +202,3 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
202202
terminator.kind = TerminatorKind::Goto { target: destination_block };
203203
}
204204
}
205-
206-
fn is_trivially_pure_copy<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
207-
use TyKind::*;
208-
match *ty.kind() {
209-
Bool | Char | Int(..) | Uint(..) | Float(..) => true,
210-
Array(element_ty, _len) => is_trivially_pure_copy(tcx, element_ty),
211-
Tuple(field_tys) => field_tys.iter().all(|x| is_trivially_pure_copy(tcx, x)),
212-
_ => false,
213-
}
214-
}

0 commit comments

Comments
 (0)