Improve wording of the drop_bounds
lint
This commit is contained in:
parent
5d34076975
commit
1deef26324
1 changed files with 20 additions and 16 deletions
|
@ -18,23 +18,27 @@ declare_lint! {
|
|||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// `Drop` bounds do not really accomplish anything. A type may have
|
||||
/// compiler-generated drop glue without implementing the `Drop` trait
|
||||
/// itself. The `Drop` trait also only has one method, `Drop::drop`, and
|
||||
/// that function is by fiat not callable in user code. So there is really
|
||||
/// no use case for using `Drop` in trait bounds.
|
||||
/// A generic trait bound of the form `T: Drop` is most likely misleading
|
||||
/// and not what the programmer intended (they probably should have used
|
||||
/// `std::mem::needs_drop` instead).
|
||||
///
|
||||
/// The most likely use case of a drop bound is to distinguish between
|
||||
/// types that have destructors and types that don't. Combined with
|
||||
/// specialization, a naive coder would write an implementation that
|
||||
/// assumed a type could be trivially dropped, then write a specialization
|
||||
/// for `T: Drop` that actually calls the destructor. Except that doing so
|
||||
/// is not correct; String, for example, doesn't actually implement Drop,
|
||||
/// but because String contains a Vec, assuming it can be trivially dropped
|
||||
/// will leak memory.
|
||||
/// `Drop` bounds do not actually indicate whether a type can be trivially
|
||||
/// dropped or not, because a composite type containing `Drop` types does
|
||||
/// not necessarily implement `Drop` itself. Naïvely, one might be tempted
|
||||
/// to write an implementation that assumes that a type can be trivially
|
||||
/// dropped while also supplying a specialization for `T: Drop` that
|
||||
/// actually calls the destructor. However, this breaks down e.g. when `T`
|
||||
/// is `String`, which does not implement `Drop` itself but contains a
|
||||
/// `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,
|
||||
Warn,
|
||||
"bounds of the form `T: Drop` are useless"
|
||||
"bounds of the form `T: Drop` are most likely incorrect"
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
|
@ -65,8 +69,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
|||
None => return,
|
||||
};
|
||||
let msg = format!(
|
||||
"bounds on `{}` are useless, consider instead \
|
||||
using `{}` to detect if a type has a destructor",
|
||||
"bounds on `{}` are most likely incorrect, consider instead \
|
||||
using `{}` to detect whether a type can be trivially dropped",
|
||||
predicate,
|
||||
cx.tcx.def_path_str(needs_drop)
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue