diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 195bd2acce0fe3ed1ee2ad7837f5eb2a5d23e836..cbc4ebe90fd091070c9ec648f8b049d8905254df 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -160,21 +160,25 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { }; let mut fn_warned = false; - let maybe_def = match expr.node { - hir::ExprCall(ref callee, _) => { - match callee.node { - hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.hir_id)), - _ => None - } - }, - hir::ExprMethodCall(..) => { - cx.tables.type_dependent_defs().get(expr.hir_id).cloned() - }, - _ => { None } - }; - if let Some(def) = maybe_def { - let def_id = def.def_id(); - fn_warned = check_must_use(cx, def_id, s.span, "return value of "); + if cx.tcx.sess.features.borrow().fn_must_use { + let maybe_def = match expr.node { + hir::ExprCall(ref callee, _) => { + match callee.node { + hir::ExprPath(ref qpath) => { + Some(cx.tables.qpath_def(qpath, callee.hir_id)) + }, + _ => None + } + }, + hir::ExprMethodCall(..) => { + cx.tables.type_dependent_defs().get(expr.hir_id).cloned() + }, + _ => None + }; + if let Some(def) = maybe_def { + let def_id = def.def_id(); + fn_warned = check_must_use(cx, def_id, s.span, "return value of "); + } } if !(ty_warned || fn_warned) { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 801343689b728f37f93700d16d979a45fd14ea7e..ee791609e8f79c285b86ab949601d30550b46f00 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -372,6 +372,9 @@ pub fn new() -> Features { // #[doc(cfg(...))] (active, doc_cfg, "1.21.0", Some(43781)), + + // allow `#[must_use]` on functions (RFC 1940) + (active, fn_must_use, "1.21.0", Some(43302)), ); declare_features! ( @@ -1014,7 +1017,7 @@ pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: Gate } pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue, - explain: &str) -> DiagnosticBuilder<'a> { + explain: &str) -> DiagnosticBuilder<'a> { let diag = &sess.span_diagnostic; let issue = match issue { @@ -1234,6 +1237,10 @@ fn visit_item(&mut self, i: &'a ast::Item) { function may change over time, for now \ a top-level `fn main()` is required"); } + if attr::contains_name(&i.attrs[..], "must_use") { + gate_feature_post!(&self, fn_must_use, i.span, + "`#[must_use]` on functions is experimental"); + } } ast::ItemKind::Struct(..) => { diff --git a/src/test/compile-fail/feature-gate-fn_must_use.rs b/src/test/compile-fail/feature-gate-fn_must_use.rs new file mode 100644 index 0000000000000000000000000000000000000000..7bb533251dc08470ec4299e6a6ef76d7fdc1df12 --- /dev/null +++ b/src/test/compile-fail/feature-gate-fn_must_use.rs @@ -0,0 +1,14 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[must_use] +fn need_to_use_it() -> bool { true } //~ ERROR `#[must_use]` on functions is experimental + +fn main() {} diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 29a2b0609fcd2dd368cede7d473fcf592448c9c5..021daf88420d15af8c22a4af44003387176f8860 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -680,6 +680,7 @@ mod must_use { mod inner { #![must_use="1400"] } #[must_use = "1400"] fn f() { } + //~^ ERROR `#[must_use]` on functions is experimental #[must_use = "1400"] struct S; diff --git a/src/test/ui/lint/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs index 5aea5f2ca06423823f51bbee89a1b0f0a66de551..c549ded4db2188ea4d06d4cd42e16c9812a95f22 100644 --- a/src/test/ui/lint/fn_must_use.rs +++ b/src/test/ui/lint/fn_must_use.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(fn_must_use)] #![warn(unused_must_use)] struct MyStruct { diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr index 20eb7452aea7163b200f252f09482f150b44ffff..242837793a0bf2f4acd1d92d6248189eeee9b443 100644 --- a/src/test/ui/lint/fn_must_use.stderr +++ b/src/test/ui/lint/fn_must_use.stderr @@ -1,18 +1,18 @@ warning: unused return value of `need_to_use_this_value` which must be used: it's important - --> $DIR/fn_must_use.rs:30:5 + --> $DIR/fn_must_use.rs:31:5 | -30 | need_to_use_this_value(); +31 | need_to_use_this_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/fn_must_use.rs:11:9 + --> $DIR/fn_must_use.rs:12:9 | -11 | #![warn(unused_must_use)] +12 | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used - --> $DIR/fn_must_use.rs:33:5 + --> $DIR/fn_must_use.rs:34:5 | -33 | m.need_to_use_this_method_value(); +34 | m.need_to_use_this_method_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^