@@ -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.
0 commit comments