Skip to content

Commit eedbfc0

Browse files
authored
Rollup merge of rust-lang#62235 - varkor:must_use-adt-components, r=Centril
Extend the `#[must_use]` lint to arrays Based on top of rust-lang#62228. r? @Centril
2 parents 60caeac + 0fccbf0 commit eedbfc0

File tree

8 files changed

+183
-11
lines changed

8 files changed

+183
-11
lines changed

src/librustc_lint/unused.rs

+41-7
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
4848
}
4949

5050
let ty = cx.tables.expr_ty(&expr);
51-
let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "");
51+
let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", false);
5252

5353
let mut fn_warned = false;
5454
let mut op_warned = false;
@@ -133,23 +133,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
133133
ty: Ty<'tcx>,
134134
expr: &hir::Expr,
135135
span: Span,
136-
descr_post_path: &str,
136+
descr_pre: &str,
137+
descr_post: &str,
138+
plural: bool,
137139
) -> bool {
138140
if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(
139141
cx.tcx.hir().get_module_parent(expr.hir_id), ty)
140142
{
141143
return true;
142144
}
143145

146+
let plural_suffix = if plural { "s" } else { "" };
147+
144148
match ty.sty {
145-
ty::Adt(def, _) => check_must_use_def(cx, def.did, span, "", descr_post_path),
149+
ty::Adt(..) if ty.is_box() => {
150+
let boxed_ty = ty.boxed_ty();
151+
let descr_pre = &format!("{}boxed ", descr_pre);
152+
check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural)
153+
}
154+
ty::Adt(def, _) => {
155+
check_must_use_def(cx, def.did, span, descr_pre, descr_post)
156+
}
146157
ty::Opaque(def, _) => {
147158
let mut has_emitted = false;
148159
for (predicate, _) in &cx.tcx.predicates_of(def).predicates {
149160
if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
150161
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
151162
let def_id = trait_ref.def_id;
152-
if check_must_use_def(cx, def_id, span, "implementer of ", "") {
163+
let descr_pre = &format!(
164+
"{}implementer{} of ",
165+
descr_pre,
166+
plural_suffix,
167+
);
168+
if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
153169
has_emitted = true;
154170
break;
155171
}
@@ -162,7 +178,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
162178
for predicate in binder.skip_binder().iter() {
163179
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
164180
let def_id = trait_ref.def_id;
165-
if check_must_use_def(cx, def_id, span, "", " trait object") {
181+
let descr_post = &format!(
182+
" trait object{}{}",
183+
plural_suffix,
184+
descr_post,
185+
);
186+
if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
166187
has_emitted = true;
167188
break;
168189
}
@@ -179,14 +200,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
179200
vec![]
180201
};
181202
for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() {
182-
let descr_post_path = &format!(" in tuple element {}", i);
203+
let descr_post = &format!(" in tuple element {}", i);
183204
let span = *spans.get(i).unwrap_or(&span);
184-
if check_must_use_ty(cx, ty, expr, span, descr_post_path) {
205+
if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural) {
185206
has_emitted = true;
186207
}
187208
}
188209
has_emitted
189210
}
211+
ty::Array(ty, len) => match len.assert_usize(cx.tcx) {
212+
// If the array is definitely non-empty, we can do `#[must_use]` checking.
213+
Some(n) if n != 0 => {
214+
let descr_pre = &format!(
215+
"{}array{} of ",
216+
descr_pre,
217+
plural_suffix,
218+
);
219+
check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, true)
220+
}
221+
// Otherwise, we don't lint, to avoid false positives.
222+
_ => false,
223+
}
190224
_ => false,
191225
}
192226
}

src/libstd/panicking.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
103103
HOOK_LOCK.write_unlock();
104104

105105
if let Hook::Custom(ptr) = old_hook {
106-
Box::from_raw(ptr);
106+
#[allow(unused_must_use)] {
107+
Box::from_raw(ptr);
108+
}
107109
}
108110
}
109111
}

src/test/run-pass/issues/issue-30530.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ pub enum Handler {
1212
}
1313

1414
fn main() {
15-
take(Handler::Default, Box::new(main));
15+
#[allow(unused_must_use)] {
16+
take(Handler::Default, Box::new(main));
17+
}
1618
}
1719

1820
#[inline(never)]

src/test/run-pass/panics/panic-handler-flail-wildly.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// run-pass
2+
23
#![allow(stable_features)]
4+
#![allow(unused_must_use)]
35

46
// ignore-emscripten no threads support
57

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

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#![deny(unused_must_use)]
2+
3+
#[must_use]
4+
struct S;
5+
6+
struct A;
7+
8+
#[must_use]
9+
trait T {}
10+
11+
impl T for A {}
12+
13+
fn empty() -> [S; 0] {
14+
[]
15+
}
16+
17+
fn singleton() -> [S; 1] {
18+
[S]
19+
}
20+
21+
fn many() -> [S; 4] {
22+
[S, S, S, S]
23+
}
24+
25+
fn array_of_impl_trait() -> [impl T; 2] {
26+
[A, A]
27+
}
28+
29+
fn impl_array() -> [(u8, Box<dyn T>); 2] {
30+
[(0, Box::new(A)), (0, Box::new(A))]
31+
}
32+
33+
fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] {
34+
[[[S], [S]]]
35+
}
36+
37+
fn main() {
38+
empty(); // ok
39+
singleton(); //~ ERROR unused array of `S` that must be used
40+
many(); //~ ERROR unused array of `S` that must be used
41+
([S], 0, ()); //~ ERROR unused array of `S` in tuple element 0 that must be used
42+
array_of_impl_trait(); //~ ERROR unused array of implementers of `T` that must be used
43+
impl_array();
44+
//~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used
45+
array_of_arrays_of_arrays();
46+
//~^ ERROR unused array of arrays of arrays of `S` that must be used
47+
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error: unused array of `S` that must be used
2+
--> $DIR/must_use-array.rs:39:5
3+
|
4+
LL | singleton();
5+
| ^^^^^^^^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/must_use-array.rs:1:9
9+
|
10+
LL | #![deny(unused_must_use)]
11+
| ^^^^^^^^^^^^^^^
12+
13+
error: unused array of `S` that must be used
14+
--> $DIR/must_use-array.rs:40:5
15+
|
16+
LL | many();
17+
| ^^^^^^^
18+
19+
error: unused array of `S` in tuple element 0 that must be used
20+
--> $DIR/must_use-array.rs:41:6
21+
|
22+
LL | ([S], 0, ());
23+
| ^^^
24+
25+
error: unused array of implementers of `T` that must be used
26+
--> $DIR/must_use-array.rs:42:5
27+
|
28+
LL | array_of_impl_trait();
29+
| ^^^^^^^^^^^^^^^^^^^^^^
30+
31+
error: unused array of boxed `T` trait objects in tuple element 1 that must be used
32+
--> $DIR/must_use-array.rs:43:5
33+
|
34+
LL | impl_array();
35+
| ^^^^^^^^^^^^^
36+
37+
error: unused array of arrays of arrays of `S` that must be used
38+
--> $DIR/must_use-array.rs:45:5
39+
|
40+
LL | array_of_arrays_of_arrays();
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
43+
error: aborting due to 6 previous errors
44+

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

+17
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,23 @@ fn get_critical() -> impl NotSoCritical + Critical + DecidedlyUnimportant {
1717
Anon {}
1818
}
1919

20+
fn get_boxed_critical() -> Box<dyn Critical> {
21+
Box::new(Anon {})
22+
}
23+
24+
fn get_nested_boxed_critical() -> Box<Box<dyn Critical>> {
25+
Box::new(Box::new(Anon {}))
26+
}
27+
28+
fn get_critical_tuple() -> (u32, Box<dyn Critical>, impl Critical, ()) {
29+
(0, get_boxed_critical(), get_critical(), ())
30+
}
31+
2032
fn main() {
2133
get_critical(); //~ ERROR unused implementer of `Critical` that must be used
34+
get_boxed_critical(); //~ ERROR unused boxed `Critical` trait object that must be used
35+
get_nested_boxed_critical();
36+
//~^ ERROR unused boxed boxed `Critical` trait object that must be used
37+
get_critical_tuple(); //~ ERROR unused boxed `Critical` trait object in tuple element 1
38+
//~^ ERROR unused implementer of `Critical` in tuple element 2
2239
}

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

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unused implementer of `Critical` that must be used
2-
--> $DIR/must_use-trait.rs:21:5
2+
--> $DIR/must_use-trait.rs:33:5
33
|
44
LL | get_critical();
55
| ^^^^^^^^^^^^^^^
@@ -10,5 +10,29 @@ note: lint level defined here
1010
LL | #![deny(unused_must_use)]
1111
| ^^^^^^^^^^^^^^^
1212

13-
error: aborting due to previous error
13+
error: unused boxed `Critical` trait object that must be used
14+
--> $DIR/must_use-trait.rs:34:5
15+
|
16+
LL | get_boxed_critical();
17+
| ^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: unused boxed boxed `Critical` trait object that must be used
20+
--> $DIR/must_use-trait.rs:35:5
21+
|
22+
LL | get_nested_boxed_critical();
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: unused boxed `Critical` trait object in tuple element 1 that must be used
26+
--> $DIR/must_use-trait.rs:37:5
27+
|
28+
LL | get_critical_tuple();
29+
| ^^^^^^^^^^^^^^^^^^^^^
30+
31+
error: unused implementer of `Critical` in tuple element 2 that must be used
32+
--> $DIR/must_use-trait.rs:37:5
33+
|
34+
LL | get_critical_tuple();
35+
| ^^^^^^^^^^^^^^^^^^^^^
36+
37+
error: aborting due to 5 previous errors
1438

0 commit comments

Comments
 (0)