Skip to content

Commit be88961

Browse files
committed
Fix handling of #[must_use] on unit and uninhabited types
1 parent 423d810 commit be88961

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

src/librustc_lint/unused.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
5959
}
6060

6161
let t = cx.tables.expr_ty(&expr);
62-
let ty_warned = match t.sty {
63-
ty::Tuple(ref tys) if tys.is_empty() => return,
64-
ty::Never => return,
62+
// FIXME(varkor): replace with `t.is_unit() || t.conservative_is_uninhabited()`.
63+
let type_permits_no_use = match t.sty {
64+
ty::Tuple(ref tys) if tys.is_empty() => true,
65+
ty::Never => true,
6566
ty::Adt(def, _) => {
6667
if def.variants.is_empty() {
67-
return;
68+
true
69+
} else {
70+
check_must_use(cx, def.did, s.span, "")
6871
}
69-
check_must_use(cx, def.did, s.span, "")
70-
},
72+
}
7173
_ => false,
7274
};
7375

@@ -95,7 +97,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
9597
if let Some(def) = maybe_def {
9698
let def_id = def.def_id();
9799
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
100+
} else if type_permits_no_use {
101+
// We don't warn about unused unit or uninhabited types.
102+
// (See https://github.com/rust-lang/rust/issues/43806 for details.)
103+
return;
98104
}
105+
99106
let must_use_op = match expr.node {
100107
// Hardcoding operators here seemed more expedient than the
101108
// refactoring that would be needed to look up the `#[must_use]`
@@ -139,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
139146
op_warned = true;
140147
}
141148

142-
if !(ty_warned || fn_warned || op_warned) {
149+
if !(type_permits_no_use || fn_warned || op_warned) {
143150
cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
144151
}
145152

@@ -233,7 +240,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
233240
.find(|&&(builtin, ty, _)| name == builtin && ty == AttributeType::CrateLevel)
234241
.is_some();
235242

236-
// Has a plugin registered this attribute as one which must be used at
243+
// Has a plugin registered this attribute as one that must be used at
237244
// the crate level?
238245
let plugin_crate = plugin_attributes.iter()
239246
.find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t)

src/test/ui/lint/must_use-unit.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(never_type)]
2+
3+
#![deny(unused_must_use)]
4+
5+
#[must_use]
6+
fn foo() {}
7+
8+
#[must_use]
9+
fn bar() -> ! {
10+
unimplemented!()
11+
}
12+
13+
fn main() {
14+
foo(); //~ unused return value of `foo`
15+
16+
bar(); //~ unused return value of `bar`
17+
}

src/test/ui/lint/must_use-unit.stderr

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: unused return value of `foo` which must be used
2+
--> $DIR/must_use-unit.rs:14:5
3+
|
4+
LL | foo(); //~ unused return value of `foo`
5+
| ^^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/must_use-unit.rs:3:9
9+
|
10+
LL | #![deny(unused_must_use)]
11+
| ^^^^^^^^^^^^^^^
12+
13+
error: unused return value of `bar` which must be used
14+
--> $DIR/must_use-unit.rs:16:5
15+
|
16+
LL | bar(); //~ unused return value of `bar`
17+
| ^^^^^^
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)