1
Fork 0

Improve wording of the drop_bounds lint

This commit is contained in:
Fabian Wolff 2021-06-30 16:42:54 +02:00
parent 5d34076975
commit 1deef26324

View file

@ -18,23 +18,27 @@ declare_lint! {
/// ///
/// ### Explanation /// ### Explanation
/// ///
/// `Drop` bounds do not really accomplish anything. A type may have /// A generic trait bound of the form `T: Drop` is most likely misleading
/// compiler-generated drop glue without implementing the `Drop` trait /// and not what the programmer intended (they probably should have used
/// itself. The `Drop` trait also only has one method, `Drop::drop`, and /// `std::mem::needs_drop` instead).
/// that function is by fiat not callable in user code. So there is really
/// no use case for using `Drop` in trait bounds.
/// ///
/// The most likely use case of a drop bound is to distinguish between /// `Drop` bounds do not actually indicate whether a type can be trivially
/// types that have destructors and types that don't. Combined with /// dropped or not, because a composite type containing `Drop` types does
/// specialization, a naive coder would write an implementation that /// not necessarily implement `Drop` itself. Naïvely, one might be tempted
/// assumed a type could be trivially dropped, then write a specialization /// to write an implementation that assumes that a type can be trivially
/// for `T: Drop` that actually calls the destructor. Except that doing so /// dropped while also supplying a specialization for `T: Drop` that
/// is not correct; String, for example, doesn't actually implement Drop, /// actually calls the destructor. However, this breaks down e.g. when `T`
/// but because String contains a Vec, assuming it can be trivially dropped /// is `String`, which does not implement `Drop` itself but contains a
/// will leak memory. /// `Vec`, which does implement `Drop`, so assuming `T` can be trivially
/// dropped would lead to a memory leak here.
///
/// Furthermore, the `Drop` trait only contains one method, `Drop::drop`,
/// which may not be called explicitly in user code (`E0040`), so there is
/// really no use case for using `Drop` in trait bounds, save perhaps for
/// some obscure corner cases, which can use `#[allow(drop_bounds)]`.
pub DROP_BOUNDS, pub DROP_BOUNDS,
Warn, Warn,
"bounds of the form `T: Drop` are useless" "bounds of the form `T: Drop` are most likely incorrect"
} }
declare_lint_pass!( declare_lint_pass!(
@ -65,8 +69,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
None => return, None => return,
}; };
let msg = format!( let msg = format!(
"bounds on `{}` are useless, consider instead \ "bounds on `{}` are most likely incorrect, consider instead \
using `{}` to detect if a type has a destructor", using `{}` to detect whether a type can be trivially dropped",
predicate, predicate,
cx.tcx.def_path_str(needs_drop) cx.tcx.def_path_str(needs_drop)
); );