+ ty::Closure(..) => Some(MustUsePath::Closure(span)),
+ ty::Generator(..) => Some(MustUsePath::Generator(span)),
+ _ => None,
+ }
+ }
+
+ fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
+ if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
+ // check for #[must_use = "..."]
+ let reason = attr.value_str();
+ Some(MustUsePath::Def(span, def_id, reason))
+ } else {
+ None
+ }
+ }
+
+ // Returns whether further errors should be suppressed because either a lint has been emitted or the type should be ignored.
+ fn check_must_use_def(
+ cx: &LateContext<'_>,
+ def_id: DefId,
+ span: Span,
+ descr_pre_path: &str,
+ descr_post_path: &str,
+ ) -> bool {
+ is_def_must_use(cx, def_id, span)
+ .map(|must_use_path| {
+ emit_must_use_untranslated(
+ cx,
+ &must_use_path,
+ descr_pre_path,
+ descr_post_path,
+ 1,
+ )
+ })
+ .is_some()
+ }
+
+ #[instrument(skip(cx), level = "debug")]
+ fn emit_must_use_untranslated(
+ cx: &LateContext<'_>,
+ path: &MustUsePath,
+ descr_pre: &str,
+ descr_post: &str,
+ plural_len: usize,
+ ) {
+ let plural_suffix = pluralize!(plural_len);
+
+ match path {
+ MustUsePath::Suppressed => {}
+ MustUsePath::Boxed(path) => {
+ let descr_pre = &format!("{}boxed ", descr_pre);
+ emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+ }
+ MustUsePath::Opaque(path) => {
+ let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix);
+ emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+ }
+ MustUsePath::TraitObject(path) => {
+ let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post);
+ emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+ }
+ MustUsePath::TupleElement(elems) => {
+ for (index, path) in elems {
+ let descr_post = &format!(" in tuple element {}", index);
+ emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
+ }
+ }
+ MustUsePath::Array(path, len) => {
+ let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix);
+ emit_must_use_untranslated(
+ cx,
+ path,
+ descr_pre,
+ descr_post,
+ plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
+ );
+ }
+ MustUsePath::Closure(span) => {