11use rustc_hir:: { Arm , Expr , ExprKind , Node } ;
22use rustc_span:: sym;
33
4- use crate :: { lints:: { DropRefDiag , DropCopyDiag , ForgetRefDiag } , LateContext , LateLintPass , LintContext } ;
4+ use crate :: {
5+ lints:: { DropCopyDiag , DropRefDiag , ForgetCopyDiag , ForgetRefDiag } ,
6+ LateContext , LateLintPass , LintContext ,
7+ } ;
58
69declare_lint ! {
710 /// The `drop_ref` lint checks for calls to `std::mem::drop` with a reference
@@ -78,7 +81,35 @@ declare_lint! {
7881 "calls to `std::mem::drop` with a value that implements Copy"
7982}
8083
81- declare_lint_pass ! ( DropForgetUseless => [ DROP_REF , FORGET_REF , DROP_COPY ] ) ;
84+ declare_lint ! {
85+ /// The `forget_copy` lint checks for calls to `std::mem::forget` with a value
86+ /// that derives the Copy trait.
87+ ///
88+ /// ### Example
89+ ///
90+ /// ```rust
91+ /// let x: i32 = 42; // i32 implements Copy
92+ /// std::mem::forget(x); // A copy of x is passed to the function, leaving the
93+ /// // original unaffected
94+ /// ```
95+ ///
96+ /// {{produces}}
97+ ///
98+ /// ### Explanation
99+ ///
100+ /// Calling `std::mem::forget` [does nothing for types that
101+ /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
102+ /// value will be copied and moved into the function on invocation.
103+ ///
104+ /// An alternative, but also valid, explanation is that Copy types do not
105+ /// implement the Drop trait, which means they have no destructors. Without a
106+ /// destructor, there is nothing for `std::mem::forget` to ignore.
107+ pub FORGET_COPY ,
108+ Warn ,
109+ "calls to `std::mem::forget` with a value that implements Copy"
110+ }
111+
112+ declare_lint_pass ! ( DropForgetUseless => [ DROP_REF , FORGET_REF , DROP_COPY , FORGET_COPY ] ) ;
82113
83114impl < ' tcx > LateLintPass < ' tcx > for DropForgetUseless {
84115 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) {
@@ -100,6 +131,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
100131 sym:: mem_drop if is_copy && !drop_is_single_call_in_arm => {
101132 cx. emit_spanned_lint ( DROP_COPY , expr. span , DropCopyDiag { arg_ty, note : arg. span } ) ;
102133 }
134+ sym:: mem_forget if is_copy => {
135+ cx. emit_spanned_lint ( FORGET_COPY , expr. span , ForgetCopyDiag { arg_ty, note : arg. span } ) ;
136+ }
103137 _ => return ,
104138 } ;
105139 }
0 commit comments