Skip to content

Commit 357bf00

Browse files
committed
Auto merge of #48925 - zackmdavis:fn_must_stabilize, r=nikomatsakis
stabilize `#[must_use]` for functions and must-use comparison operators (RFC 1940) r? @nikomatsakis
2 parents 17841cc + 3dbdccc commit 357bf00

20 files changed

+167
-337
lines changed

src/doc/unstable-book/src/language-features/fn-must-use.md

-30
This file was deleted.

src/liballoc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
#![feature(dropck_eyepatch)]
9797
#![feature(exact_size_is_empty)]
9898
#![feature(fmt_internals)]
99-
#![feature(fn_must_use)]
99+
#![cfg_attr(stage0, feature(fn_must_use))]
100100
#![feature(from_ref)]
101101
#![feature(fundamental)]
102102
#![feature(lang_items)]

src/liballoc/tests/slice.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,7 @@ fn test_box_slice_clone() {
12821282
}
12831283

12841284
#[test]
1285+
#[allow(unused_must_use)] // here, we care about the side effects of `.clone()`
12851286
#[cfg_attr(target_os = "emscripten", ignore)]
12861287
fn test_box_slice_clone_panics() {
12871288
use std::sync::Arc;

src/libcore/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@
7676
#![feature(doc_cfg)]
7777
#![feature(doc_spotlight)]
7878
#![feature(extern_types)]
79-
#![feature(fn_must_use)]
8079
#![feature(fundamental)]
8180
#![feature(intrinsics)]
8281
#![feature(iterator_flatten)]
@@ -114,6 +113,7 @@
114113

115114
#![cfg_attr(stage0, feature(target_feature))]
116115
#![cfg_attr(stage0, feature(cfg_target_feature))]
116+
#![cfg_attr(stage0, feature(fn_must_use))]
117117

118118
#[prelude_import]
119119
#[allow(unused)]

src/librustc_lint/unused.rs

+53-47
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use rustc::hir::def::Def;
1112
use rustc::hir::def_id::DefId;
1213
use rustc::ty;
1314
use rustc::ty::adjustment;
@@ -72,54 +73,59 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
7273

7374
let mut fn_warned = false;
7475
let mut op_warned = false;
75-
if cx.tcx.features().fn_must_use {
76-
let maybe_def = match expr.node {
77-
hir::ExprCall(ref callee, _) => {
78-
match callee.node {
79-
hir::ExprPath(ref qpath) => {
80-
Some(cx.tables.qpath_def(qpath, callee.hir_id))
81-
},
82-
_ => None
83-
}
84-
},
85-
hir::ExprMethodCall(..) => {
86-
cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
87-
},
88-
_ => None
89-
};
90-
if let Some(def) = maybe_def {
91-
let def_id = def.def_id();
92-
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
93-
}
94-
let must_use_op = match expr.node {
95-
// Hardcoding operators here seemed more expedient than the
96-
// refactoring that would be needed to look up the `#[must_use]`
97-
// attribute which does exist on the comparison trait methods
98-
hir::ExprBinary(bin_op, ..) => {
99-
match bin_op.node {
100-
hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
101-
Some("comparison")
102-
},
103-
hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => {
104-
Some("arithmetic operation")
105-
},
106-
hir::BiAnd | hir::BiOr => {
107-
Some("logical operation")
108-
},
109-
hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => {
110-
Some("bitwise operation")
111-
},
112-
}
113-
},
114-
hir::ExprUnary(..) => Some("unary operation"),
115-
_ => None
116-
};
117-
if let Some(must_use_op) = must_use_op {
118-
cx.span_lint(UNUSED_MUST_USE, expr.span,
119-
&format!("unused {} which must be used", must_use_op));
120-
op_warned = true;
121-
}
76+
let maybe_def = match expr.node {
77+
hir::ExprCall(ref callee, _) => {
78+
match callee.node {
79+
hir::ExprPath(ref qpath) => {
80+
let def = cx.tables.qpath_def(qpath, callee.hir_id);
81+
if let Def::Fn(_) = def {
82+
Some(def)
83+
} else { // `Def::Local` if it was a closure, for which we
84+
None // do not currently support must-use linting
85+
}
86+
},
87+
_ => None
88+
}
89+
},
90+
hir::ExprMethodCall(..) => {
91+
cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
92+
},
93+
_ => None
94+
};
95+
if let Some(def) = maybe_def {
96+
let def_id = def.def_id();
97+
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
12298
}
99+
let must_use_op = match expr.node {
100+
// Hardcoding operators here seemed more expedient than the
101+
// refactoring that would be needed to look up the `#[must_use]`
102+
// attribute which does exist on the comparison trait methods
103+
hir::ExprBinary(bin_op, ..) => {
104+
match bin_op.node {
105+
hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
106+
Some("comparison")
107+
},
108+
hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => {
109+
Some("arithmetic operation")
110+
},
111+
hir::BiAnd | hir::BiOr => {
112+
Some("logical operation")
113+
},
114+
hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => {
115+
Some("bitwise operation")
116+
},
117+
}
118+
},
119+
hir::ExprUnary(..) => Some("unary operation"),
120+
_ => None
121+
};
122+
123+
if let Some(must_use_op) = must_use_op {
124+
cx.span_lint(UNUSED_MUST_USE, expr.span,
125+
&format!("unused {} which must be used", must_use_op));
126+
op_warned = true;
127+
}
128+
123129
if !(ty_warned || fn_warned || op_warned) {
124130
cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
125131
}

src/libstd/ffi/c_str.rs

+2
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,7 @@ impl CStr {
988988
/// behavior when `ptr` is used inside the `unsafe` block:
989989
///
990990
/// ```no_run
991+
/// # #![allow(unused_must_use)]
991992
/// use std::ffi::{CString};
992993
///
993994
/// let ptr = CString::new("Hello").unwrap().as_ptr();
@@ -1003,6 +1004,7 @@ impl CStr {
10031004
/// To fix the problem, bind the `CString` to a local variable:
10041005
///
10051006
/// ```no_run
1007+
/// # #![allow(unused_must_use)]
10061008
/// use std::ffi::{CString};
10071009
///
10081010
/// let hello = CString::new("Hello").unwrap();

src/libstd/sync/mpsc/select.rs

+2
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ mod tests {
518518
}
519519
}
520520

521+
#[allow(unused_must_use)]
521522
#[test]
522523
fn cloning() {
523524
let (tx1, rx1) = channel::<i32>();
@@ -540,6 +541,7 @@ mod tests {
540541
tx3.send(()).unwrap();
541542
}
542543

544+
#[allow(unused_must_use)]
543545
#[test]
544546
fn cloning2() {
545547
let (tx1, rx1) = channel::<i32>();

src/libsyntax/feature_gate.rs

+3-19
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,6 @@ declare_features! (
369369
// #[doc(include="some-file")]
370370
(active, external_doc, "1.22.0", Some(44732), None),
371371

372-
// allow `#[must_use]` on functions and comparison operators (RFC 1940)
373-
(active, fn_must_use, "1.21.0", Some(43302), None),
374-
375372
// Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
376373
(active, non_exhaustive, "1.22.0", Some(44109), None),
377374

@@ -591,6 +588,8 @@ declare_features! (
591588
(accepted, target_feature, "1.27.0", None, None),
592589
// Trait object syntax with `dyn` prefix
593590
(accepted, dyn_trait, "1.27.0", Some(44662), None),
591+
// allow `#[must_use]` on functions; and, must-use operators (RFC 1940)
592+
(accepted, fn_must_use, "1.27.0", Some(43302), None),
594593
);
595594

596595
// If you change this, please modify src/doc/unstable-book as well. You must
@@ -1545,11 +1544,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
15451544
function may change over time, for now \
15461545
a top-level `fn main()` is required");
15471546
}
1548-
if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
1549-
gate_feature_post!(&self, fn_must_use, attr.span,
1550-
"`#[must_use]` on functions is experimental",
1551-
GateStrength::Soft);
1552-
}
15531547
}
15541548

15551549
ast::ItemKind::Struct(..) => {
@@ -1581,7 +1575,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
15811575
"trait aliases are not yet fully implemented");
15821576
}
15831577

1584-
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
1578+
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
15851579
if polarity == ast::ImplPolarity::Negative {
15861580
gate_feature_post!(&self, optin_builtin_traits,
15871581
i.span,
@@ -1594,16 +1588,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
15941588
i.span,
15951589
"specialization is unstable");
15961590
}
1597-
1598-
for impl_item in impl_items {
1599-
if let ast::ImplItemKind::Method(..) = impl_item.node {
1600-
if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
1601-
gate_feature_post!(&self, fn_must_use, attr.span,
1602-
"`#[must_use]` on methods is experimental",
1603-
GateStrength::Soft);
1604-
}
1605-
}
1606-
}
16071591
}
16081592

16091593
ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {

src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs

-22
This file was deleted.

src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr

-8
This file was deleted.

src/test/ui/feature-gate-fn_must_use.rs

-31
This file was deleted.

src/test/ui/feature-gate-fn_must_use.stderr

-24
This file was deleted.

src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs

-1
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,6 @@ mod must_use {
661661
mod inner { #![must_use="1400"] }
662662

663663
#[must_use = "1400"] fn f() { }
664-
//~^ WARN `#[must_use]` on functions is experimental
665664

666665
#[must_use = "1400"] struct S;
667666

0 commit comments

Comments
 (0)