diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 75337634d3fda..0abb89d147634 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -620,6 +620,9 @@ declare_features! ( /// Allows capturing disjoint fields in a closure/generator (RFC 2229). (active, capture_disjoint_fields, "1.49.0", Some(53488), None), + /// Allow `#[may_ignore]` attribute. + (active, may_ignore, "1.50.0", Some(99999999), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index fa8edba629e92..1b6e0ebb70872 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -207,6 +207,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(must_use, AssumedUsed, template!(Word, NameValueStr: "reason")), + gated!(may_ignore, AssumedUsed, template!(Word), experimental!(may_ignore)), // FIXME(#14407) ungated!( deprecated, Normal, diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 2a5ad5e6c98a6..b58afcd21053a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -101,11 +101,6 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { return; } - let ty = cx.typeck_results().expr_ty(&expr); - let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1); - - let mut fn_warned = false; - let mut op_warned = false; let maybe_def_id = match expr.kind { hir::ExprKind::Call(ref callee, _) => { match callee.kind { @@ -123,6 +118,21 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { hir::ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id), _ => None, }; + + if let Some(def_id) = maybe_def_id { + for attr in cx.tcx.get_attrs(def_id).iter() { + if cx.sess().check_name(attr, sym::may_ignore) { + // Don't warn if the function was marked as #[may_ignore]. + return; + } + } + } + + let ty = cx.typeck_results().expr_ty(&expr); + let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1); + + let mut fn_warned = false; + let mut op_warned = false; if let Some(def_id) = maybe_def_id { fn_warned = check_must_use_def(cx, def_id, s.span, "return value of ", ""); } else if type_permits_lack_of_use { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d5fccdeb189cc..857d8b7c9ad99 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -681,6 +681,7 @@ symbols! { maxnumf32, maxnumf64, may_dangle, + may_ignore, maybe_uninit, maybe_uninit_uninit, maybe_uninit_zeroed, diff --git a/src/test/ui/feature-gate-may_ignore.rs b/src/test/ui/feature-gate-may_ignore.rs new file mode 100644 index 0000000000000..4494961090849 --- /dev/null +++ b/src/test/ui/feature-gate-may_ignore.rs @@ -0,0 +1,4 @@ +#[may_ignore] +//~^ ERROR the `#[may_ignore]` attribute is an experimental feature [E0658] +fn main() { +} diff --git a/src/test/ui/feature-gate-may_ignore.stderr b/src/test/ui/feature-gate-may_ignore.stderr new file mode 100644 index 0000000000000..cf4735bc3ef28 --- /dev/null +++ b/src/test/ui/feature-gate-may_ignore.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[may_ignore]` attribute is an experimental feature + --> $DIR/feature-gate-may_ignore.rs:1:1 + | +LL | #[may_ignore] + | ^^^^^^^^^^^^^ + | + = note: see issue #99999999 for more information + = help: add `#![feature(may_ignore)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/may_ignore.rs b/src/test/ui/may_ignore.rs new file mode 100644 index 0000000000000..efbcf16fa3aa0 --- /dev/null +++ b/src/test/ui/may_ignore.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(may_ignore)] +#![warn(unused_must_use)] + +fn warn() -> Result { + Err(1) +} + +#[may_ignore] +fn no_warn() -> Result { + Err(2) +} + +fn main() { + warn(); //~ WARN [unused_must_use] + no_warn(); +} diff --git a/src/test/ui/may_ignore.stderr b/src/test/ui/may_ignore.stderr new file mode 100644 index 0000000000000..c4527b19c1066 --- /dev/null +++ b/src/test/ui/may_ignore.stderr @@ -0,0 +1,15 @@ +warning: unused `std::result::Result` that must be used + --> $DIR/may_ignore.rs:16:5 + | +LL | warn(); + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/may_ignore.rs:4:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + = note: this `Result` may be an `Err` variant, which should be handled + +warning: 1 warning emitted +