@@ -46,14 +46,16 @@ use rustc_middle::lint::in_external_macro;
4646use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf } ;
4747use rustc_middle:: ty:: print:: with_no_trimmed_paths;
4848use rustc_middle:: ty:: subst:: GenericArgKind ;
49+ use rustc_middle:: ty:: List ;
4950use rustc_middle:: ty:: { self , Instance , Ty , TyCtxt , VariantDef } ;
5051use rustc_session:: lint:: { BuiltinLintDiagnostics , FutureIncompatibilityReason } ;
5152use rustc_span:: edition:: Edition ;
5253use rustc_span:: source_map:: Spanned ;
5354use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
5455use rustc_span:: { BytePos , InnerSpan , Span } ;
5556use rustc_target:: abi:: { Abi , VariantIdx } ;
56- use rustc_trait_selection:: traits:: { self , misc:: can_type_implement_copy} ;
57+ use rustc_trait_selection:: infer:: { InferCtxtExt , TyCtxtInferExt } ;
58+ use rustc_trait_selection:: traits:: { self , misc:: can_type_implement_copy, EvaluationResult } ;
5759
5860use crate :: nonstandard_style:: { method_context, MethodLateContext } ;
5961
@@ -750,10 +752,40 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
750752 if def. has_dtor ( cx. tcx ) {
751753 return ;
752754 }
755+
756+ // If the type contains a raw pointer, it may represent something like a handle,
757+ // and recommending Copy might be a bad idea.
758+ for field in def. all_fields ( ) {
759+ let did = field. did ;
760+ if cx. tcx . type_of ( did) . is_unsafe_ptr ( ) {
761+ return ;
762+ }
763+ }
753764 let param_env = ty:: ParamEnv :: empty ( ) ;
754765 if ty. is_copy_modulo_regions ( cx. tcx , param_env) {
755766 return ;
756767 }
768+
769+ // We shouldn't recommend implementing `Copy` on stateful things,
770+ // such as iterators.
771+ if let Some ( iter_trait) = cx. tcx . get_diagnostic_item ( sym:: Iterator ) {
772+ if cx. tcx . infer_ctxt ( ) . enter ( |infer_ctxt| {
773+ infer_ctxt. type_implements_trait ( iter_trait, ty, List :: empty ( ) , param_env)
774+ == EvaluationResult :: EvaluatedToOk
775+ } ) {
776+ return ;
777+ }
778+ }
779+
780+ // Default value of clippy::trivially_copy_pass_by_ref
781+ const MAX_SIZE : u64 = 256 ;
782+
783+ if let Some ( size) = cx. layout_of ( ty) . ok ( ) . map ( |l| l. size . bytes ( ) ) {
784+ if size > MAX_SIZE {
785+ return ;
786+ }
787+ }
788+
757789 if can_type_implement_copy (
758790 cx. tcx ,
759791 param_env,
0 commit comments