Skip to content

Commit f88efac

Browse files
authored
Rollup merge of rust-lang#138360 - Urgau:fix-fp-expr_or_init, r=wesleywiser
Fix false-positive in `expr_or_init` and in the `invalid_from_utf8` lint This PR fixes the logic for finding initializer in the `expr_or_init` and `expr_or_init_with_outside_body` functions. If the binding were to be mutable (`let mut`), the logic wouldn't consider that the initializer expression could have been modified and would return the init expression even-trough multiple subsequent assignments could have been done. Example: ```rust let mut a = [99, 108, 130, 105, 112, 112]; // invalid, not UTF-8 loop { a = *b"clippy"; // valid break; } std::str::from_utf8_mut(&mut a); // currently warns, with this PR it doesn't ``` This PR modifies the logic to excludes mutable let bindings. Found when using `expr_or_init` in rust-lang#119220. r? compiler
2 parents 15148c5 + faa5b3f commit f88efac

File tree

3 files changed

+58
-64
lines changed

3 files changed

+58
-64
lines changed

compiler/rustc_lint/src/context.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use std::cell::Cell;
77
use std::slice;
88

9+
use rustc_ast::BindingMode;
910
use rustc_data_structures::fx::FxIndexMap;
1011
use rustc_data_structures::sync;
1112
use rustc_data_structures::unord::UnordMap;
@@ -14,6 +15,7 @@ use rustc_feature::Features;
1415
use rustc_hir::def::Res;
1516
use rustc_hir::def_id::{CrateNum, DefId};
1617
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
18+
use rustc_hir::{Pat, PatKind};
1719
use rustc_middle::bug;
1820
use rustc_middle::middle::privacy::EffectiveVisibilities;
1921
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
@@ -890,7 +892,12 @@ impl<'tcx> LateContext<'tcx> {
890892
}
891893
&& let Some(init) = match parent_node {
892894
hir::Node::Expr(expr) => Some(expr),
893-
hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
895+
hir::Node::LetStmt(hir::LetStmt {
896+
init,
897+
// Binding is immutable, init cannot be re-assigned
898+
pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
899+
..
900+
}) => *init,
894901
_ => None,
895902
}
896903
{
@@ -935,7 +942,12 @@ impl<'tcx> LateContext<'tcx> {
935942
}
936943
&& let Some(init) = match parent_node {
937944
hir::Node::Expr(expr) => Some(expr),
938-
hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
945+
hir::Node::LetStmt(hir::LetStmt {
946+
init,
947+
// Binding is immutable, init cannot be re-assigned
948+
pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
949+
..
950+
}) => *init,
939951
hir::Node::Item(item) => match item.kind {
940952
hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => {
941953
Some(self.tcx.hir_body(body_id).value)

tests/ui/lint/invalid_from_utf8.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,21 @@ pub fn from_utf8() {
128128
}
129129

130130
pub fn from_utf8_with_indirections() {
131-
let mut a = [99, 108, 130, 105, 112, 112, 121];
132-
std::str::from_utf8_mut(&mut a);
133-
//~^ WARN calls to `std::str::from_utf8_mut`
134-
str::from_utf8_mut(&mut a);
135-
//~^ WARN calls to `str::from_utf8_mut`
136-
let mut b = &mut a;
137-
let mut c = b;
138-
std::str::from_utf8_mut(c);
139-
//~^ WARN calls to `std::str::from_utf8_mut`
140-
str::from_utf8_mut(c);
141-
//~^ WARN calls to `str::from_utf8_mut`
142-
let mut c = &[99, 108, 130, 105, 112, 112, 121];
131+
// NOTE: We used to lint on the patterns below, but due to the
132+
// binding being mutable it could be changed between the
133+
// declaration and the call and that would have created a
134+
// false-positive, so until we can reliably avoid those false
135+
// postive we don't lint on them. Example of FP below.
136+
//
137+
// let mut a = [99, 108, 130, 105, 112, 112, 121];
138+
// std::str::from_utf8_mut(&mut a);
139+
// str::from_utf8_mut(&mut a);
140+
// let mut b = &mut a;
141+
// let mut c = b;
142+
// std::str::from_utf8_mut(c);
143+
// str::from_utf8_mut(c);
144+
145+
let c = &[99, 108, 130, 105, 112, 112, 121];
143146
std::str::from_utf8(c);
144147
//~^ WARN calls to `std::str::from_utf8`
145148
str::from_utf8(c);
@@ -164,6 +167,20 @@ pub fn from_utf8_with_indirections() {
164167
//~^ WARN calls to `std::str::from_utf8`
165168
str::from_utf8(INVALID_4);
166169
//~^ WARN calls to `str::from_utf8`
170+
171+
let mut a = [99, 108, 130, 105, 112, 112, 121]; // invalid
172+
loop {
173+
a = [99, 108, 130, 105, 112, 112, 121]; // still invalid, but too complex
174+
break;
175+
}
176+
std::str::from_utf8_mut(&mut a);
177+
178+
let mut a = [99, 108, 130, 105, 112, 112]; // invalid
179+
loop {
180+
a = *b"clippy"; // valid
181+
break;
182+
}
183+
std::str::from_utf8_mut(&mut a);
167184
}
168185

169186
fn main() {}

tests/ui/lint/invalid_from_utf8.stderr

+15-50
Original file line numberDiff line numberDiff line change
@@ -202,68 +202,33 @@ LL | str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
202202
| |
203203
| the literal was valid UTF-8 up to the 2 bytes
204204

205-
warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
206-
--> $DIR/invalid_from_utf8.rs:132:5
207-
|
208-
LL | let mut a = [99, 108, 130, 105, 112, 112, 121];
209-
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
210-
LL | std::str::from_utf8_mut(&mut a);
211-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
212-
213-
warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
214-
--> $DIR/invalid_from_utf8.rs:134:5
215-
|
216-
LL | let mut a = [99, 108, 130, 105, 112, 112, 121];
217-
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
218-
...
219-
LL | str::from_utf8_mut(&mut a);
220-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
221-
222-
warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
223-
--> $DIR/invalid_from_utf8.rs:138:5
224-
|
225-
LL | let mut a = [99, 108, 130, 105, 112, 112, 121];
226-
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
227-
...
228-
LL | std::str::from_utf8_mut(c);
229-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
230-
231-
warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
232-
--> $DIR/invalid_from_utf8.rs:140:5
233-
|
234-
LL | let mut a = [99, 108, 130, 105, 112, 112, 121];
235-
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
236-
...
237-
LL | str::from_utf8_mut(c);
238-
| ^^^^^^^^^^^^^^^^^^^^^
239-
240205
warning: calls to `std::str::from_utf8` with an invalid literal always return an error
241-
--> $DIR/invalid_from_utf8.rs:143:5
206+
--> $DIR/invalid_from_utf8.rs:146:5
242207
|
243-
LL | let mut c = &[99, 108, 130, 105, 112, 112, 121];
244-
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
208+
LL | let c = &[99, 108, 130, 105, 112, 112, 121];
209+
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
245210
LL | std::str::from_utf8(c);
246211
| ^^^^^^^^^^^^^^^^^^^^^^
247212

248213
warning: calls to `str::from_utf8` with an invalid literal always return an error
249-
--> $DIR/invalid_from_utf8.rs:145:5
214+
--> $DIR/invalid_from_utf8.rs:148:5
250215
|
251-
LL | let mut c = &[99, 108, 130, 105, 112, 112, 121];
252-
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
216+
LL | let c = &[99, 108, 130, 105, 112, 112, 121];
217+
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
253218
...
254219
LL | str::from_utf8(c);
255220
| ^^^^^^^^^^^^^^^^^
256221

257222
warning: calls to `std::str::from_utf8` with an invalid literal always return an error
258-
--> $DIR/invalid_from_utf8.rs:148:5
223+
--> $DIR/invalid_from_utf8.rs:151:5
259224
|
260225
LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
261226
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
262227
LL | std::str::from_utf8(&INVALID_1);
263228
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
264229

265230
warning: calls to `str::from_utf8` with an invalid literal always return an error
266-
--> $DIR/invalid_from_utf8.rs:150:5
231+
--> $DIR/invalid_from_utf8.rs:153:5
267232
|
268233
LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
269234
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -272,15 +237,15 @@ LL | str::from_utf8(&INVALID_1);
272237
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
273238

274239
warning: calls to `std::str::from_utf8` with an invalid literal always return an error
275-
--> $DIR/invalid_from_utf8.rs:153:5
240+
--> $DIR/invalid_from_utf8.rs:156:5
276241
|
277242
LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
278243
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
279244
LL | std::str::from_utf8(&INVALID_2);
280245
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
281246

282247
warning: calls to `str::from_utf8` with an invalid literal always return an error
283-
--> $DIR/invalid_from_utf8.rs:155:5
248+
--> $DIR/invalid_from_utf8.rs:158:5
284249
|
285250
LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
286251
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -289,15 +254,15 @@ LL | str::from_utf8(&INVALID_2);
289254
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
290255

291256
warning: calls to `std::str::from_utf8` with an invalid literal always return an error
292-
--> $DIR/invalid_from_utf8.rs:158:5
257+
--> $DIR/invalid_from_utf8.rs:161:5
293258
|
294259
LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
295260
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
296261
LL | std::str::from_utf8(INVALID_3);
297262
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
298263

299264
warning: calls to `str::from_utf8` with an invalid literal always return an error
300-
--> $DIR/invalid_from_utf8.rs:160:5
265+
--> $DIR/invalid_from_utf8.rs:163:5
301266
|
302267
LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
303268
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -306,21 +271,21 @@ LL | str::from_utf8(INVALID_3);
306271
| ^^^^^^^^^^^^^^^^^^^^^^^^^
307272

308273
warning: calls to `std::str::from_utf8` with an invalid literal always return an error
309-
--> $DIR/invalid_from_utf8.rs:163:5
274+
--> $DIR/invalid_from_utf8.rs:166:5
310275
|
311276
LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
312277
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
313278
LL | std::str::from_utf8(INVALID_4);
314279
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
315280

316281
warning: calls to `str::from_utf8` with an invalid literal always return an error
317-
--> $DIR/invalid_from_utf8.rs:165:5
282+
--> $DIR/invalid_from_utf8.rs:168:5
318283
|
319284
LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
320285
| ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
321286
...
322287
LL | str::from_utf8(INVALID_4);
323288
| ^^^^^^^^^^^^^^^^^^^^^^^^^
324289

325-
warning: 38 warnings emitted
290+
warning: 34 warnings emitted
326291

0 commit comments

Comments
 (0)