Skip to content

Commit bbb781e

Browse files
committed
Auto merge of rust-lang#16589 - rosefromthedead:unresolved-ident, r=Veykril
feat: add unresolved-ident diagnostic This should cover missing local variables and missing unit structs and the like. It's conservatively marked experimental
2 parents e6b96db + 1e448f8 commit bbb781e

17 files changed

+130
-43
lines changed

crates/hir-ty/src/infer.rs

+3
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ pub enum InferenceDiagnostic {
221221
UnresolvedAssocItem {
222222
id: ExprOrPatId,
223223
},
224+
UnresolvedIdent {
225+
expr: ExprId,
226+
},
224227
// FIXME: This should be emitted in body lowering
225228
BreakOutsideOfLoop {
226229
expr: ExprId,

crates/hir-ty/src/infer/expr.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use hir_def::{
1313
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
1414
},
1515
lang_item::{LangItem, LangItemTarget},
16-
path::{GenericArg, GenericArgs},
16+
path::{GenericArg, GenericArgs, Path},
1717
BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId,
1818
};
1919
use hir_expand::name::{name, Name};
@@ -439,7 +439,17 @@ impl InferenceContext<'_> {
439439
}
440440
Expr::Path(p) => {
441441
let g = self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, tgt_expr);
442-
let ty = self.infer_path(p, tgt_expr.into()).unwrap_or_else(|| self.err_ty());
442+
let ty = match self.infer_path(p, tgt_expr.into()) {
443+
Some(ty) => ty,
444+
None => {
445+
if matches!(p, Path::Normal { mod_path, .. } if mod_path.is_ident()) {
446+
self.push_diagnostic(InferenceDiagnostic::UnresolvedIdent {
447+
expr: tgt_expr,
448+
});
449+
}
450+
self.err_ty()
451+
}
452+
};
443453
self.resolver.reset_to_guard(g);
444454
ty
445455
}

crates/hir/src/diagnostics.rs

+10
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ diagnostics![
8787
UnresolvedMacroCall,
8888
UnresolvedMethodCall,
8989
UnresolvedModule,
90+
UnresolvedIdent,
9091
UnresolvedProcMacro,
9192
UnusedMut,
9293
UnusedVariable,
@@ -242,6 +243,11 @@ pub struct UnresolvedAssocItem {
242243
pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, Either<ast::Pat, ast::SelfParam>>>>,
243244
}
244245

246+
#[derive(Debug)]
247+
pub struct UnresolvedIdent {
248+
pub expr: InFile<AstPtr<ast::Expr>>,
249+
}
250+
245251
#[derive(Debug)]
246252
pub struct PrivateField {
247253
pub expr: InFile<AstPtr<ast::Expr>>,
@@ -588,6 +594,10 @@ impl AnyDiagnostic {
588594
};
589595
UnresolvedAssocItem { expr_or_pat }.into()
590596
}
597+
&InferenceDiagnostic::UnresolvedIdent { expr } => {
598+
let expr = expr_syntax(expr);
599+
UnresolvedIdent { expr }.into()
600+
}
591601
&InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => {
592602
let expr = expr_syntax(expr);
593603
BreakOutsideOfLoop { expr, is_break, bad_value_break }.into()

crates/ide-diagnostics/src/handlers/inactive_code.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ fn f() {
6060
#[cfg(a)] let x = 0; // let statement
6161
//^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
6262
63+
fn abc() {}
6364
abc(#[cfg(a)] 0);
6465
//^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
6566
let x = Struct {

crates/ide-diagnostics/src/handlers/incorrect_case.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ impl BAD_TRAIT for () {
512512
fn BadFunction() {}
513513
}
514514
"#,
515-
std::iter::once("unused_variables".to_owned()),
515+
&["unused_variables"],
516516
);
517517
}
518518

crates/ide-diagnostics/src/handlers/missing_fields.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,8 @@ struct TestStruct { one: i32, two: i64 }
634634
635635
fn test_fn() {
636636
let one = 1;
637-
let s = TestStruct{ ..a };
637+
let a = TestStruct{ one, two: 2 };
638+
let _ = TestStruct{ ..a };
638639
}
639640
"#,
640641
);

crates/ide-diagnostics/src/handlers/missing_match_arms.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ pub(crate) fn missing_match_arms(
1818
#[cfg(test)]
1919
mod tests {
2020
use crate::{
21-
tests::{check_diagnostics, check_diagnostics_with_config},
21+
tests::{
22+
check_diagnostics, check_diagnostics_with_config, check_diagnostics_with_disabled,
23+
},
2224
DiagnosticsConfig,
2325
};
2426

@@ -282,7 +284,7 @@ fn main() {
282284
cov_mark::check_count!(validate_match_bailed_out, 4);
283285
// Match statements with arms that don't match the
284286
// expression pattern do not fire this diagnostic.
285-
check_diagnostics(
287+
check_diagnostics_with_disabled(
286288
r#"
287289
enum Either { A, B }
288290
enum Either2 { C, D }
@@ -307,6 +309,7 @@ fn main() {
307309
match Unresolved::Bar { Unresolved::Baz => () }
308310
}
309311
"#,
312+
&["E0425"],
310313
);
311314
}
312315

@@ -397,11 +400,11 @@ fn main() {
397400
match loop {} {
398401
Either::A => (),
399402
}
400-
match loop { break Foo::A } {
401-
//^^^^^^^^^^^^^^^^^^^^^ error: missing match arm: `B` not covered
403+
match loop { break Either::A } {
404+
//^^^^^^^^^^^^^^^^^^^^^^^^ error: missing match arm: `B` not covered
402405
Either::A => (),
403406
}
404-
match loop { break Foo::A } {
407+
match loop { break Either::A } {
405408
Either::A => (),
406409
Either::B => (),
407410
}
@@ -977,7 +980,7 @@ fn f(ty: Enum) {
977980
#[test]
978981
fn unexpected_ty_fndef() {
979982
cov_mark::check!(validate_match_bailed_out);
980-
check_diagnostics(
983+
check_diagnostics_with_disabled(
981984
r"
982985
enum Exp {
983986
Tuple(()),
@@ -987,6 +990,7 @@ fn f() {
987990
Exp::Tuple => {}
988991
}
989992
}",
993+
&["E0425"],
990994
);
991995
}
992996

crates/ide-diagnostics/src/handlers/mutability_errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ fn main(b: bool) {
448448
&mut x;
449449
}
450450
"#,
451-
std::iter::once("remove-unnecessary-else".to_owned()),
451+
&["remove-unnecessary-else"],
452452
);
453453
check_diagnostics_with_disabled(
454454
r#"
@@ -463,7 +463,7 @@ fn main(b: bool) {
463463
&mut x;
464464
}
465465
"#,
466-
std::iter::once("remove-unnecessary-else".to_owned()),
466+
&["remove-unnecessary-else"],
467467
);
468468
}
469469

crates/ide-diagnostics/src/handlers/remove_trailing_return.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ fn foo(x: usize) -> u8 {
140140
} //^^^^^^^^^ 💡 weak: replace return <expr>; with <expr>
141141
}
142142
"#,
143-
std::iter::once("remove-unnecessary-else".to_owned()),
143+
&["remove-unnecessary-else"],
144144
);
145145
}
146146

crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs

+25-17
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,11 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &RemoveUnnecessaryElse) -> Option<Vec<
9595

9696
#[cfg(test)]
9797
mod tests {
98-
use crate::tests::{check_diagnostics, check_diagnostics_with_disabled, check_fix};
99-
100-
fn check_diagnostics_with_needless_return_disabled(ra_fixture: &str) {
101-
check_diagnostics_with_disabled(ra_fixture, std::iter::once("needless_return".to_owned()));
102-
}
98+
use crate::tests::{check_diagnostics_with_disabled, check_fix};
10399

104100
#[test]
105101
fn remove_unnecessary_else_for_return() {
106-
check_diagnostics_with_needless_return_disabled(
102+
check_diagnostics_with_disabled(
107103
r#"
108104
fn test() {
109105
if foo {
@@ -114,6 +110,7 @@ fn test() {
114110
}
115111
}
116112
"#,
113+
&["needless_return", "E0425"],
117114
);
118115
check_fix(
119116
r#"
@@ -138,7 +135,7 @@ fn test() {
138135

139136
#[test]
140137
fn remove_unnecessary_else_for_return2() {
141-
check_diagnostics_with_needless_return_disabled(
138+
check_diagnostics_with_disabled(
142139
r#"
143140
fn test() {
144141
if foo {
@@ -151,6 +148,7 @@ fn test() {
151148
}
152149
}
153150
"#,
151+
&["needless_return", "E0425"],
154152
);
155153
check_fix(
156154
r#"
@@ -181,7 +179,7 @@ fn test() {
181179

182180
#[test]
183181
fn remove_unnecessary_else_for_return3() {
184-
check_diagnostics_with_needless_return_disabled(
182+
check_diagnostics_with_disabled(
185183
r#"
186184
fn test(a: bool) -> i32 {
187185
if a {
@@ -192,6 +190,7 @@ fn test(a: bool) -> i32 {
192190
}
193191
}
194192
"#,
193+
&["needless_return", "E0425"],
195194
);
196195
check_fix(
197196
r#"
@@ -216,7 +215,7 @@ fn test(a: bool) -> i32 {
216215

217216
#[test]
218217
fn remove_unnecessary_else_for_return_in_child_if_expr() {
219-
check_diagnostics_with_needless_return_disabled(
218+
check_diagnostics_with_disabled(
220219
r#"
221220
fn test() {
222221
if foo {
@@ -229,6 +228,7 @@ fn test() {
229228
}
230229
}
231230
"#,
231+
&["needless_return", "E0425"],
232232
);
233233
check_fix(
234234
r#"
@@ -294,7 +294,7 @@ fn test() {
294294

295295
#[test]
296296
fn remove_unnecessary_else_for_break() {
297-
check_diagnostics(
297+
check_diagnostics_with_disabled(
298298
r#"
299299
fn test() {
300300
loop {
@@ -307,6 +307,7 @@ fn test() {
307307
}
308308
}
309309
"#,
310+
&["E0425"],
310311
);
311312
check_fix(
312313
r#"
@@ -335,7 +336,7 @@ fn test() {
335336

336337
#[test]
337338
fn remove_unnecessary_else_for_continue() {
338-
check_diagnostics(
339+
check_diagnostics_with_disabled(
339340
r#"
340341
fn test() {
341342
loop {
@@ -348,6 +349,7 @@ fn test() {
348349
}
349350
}
350351
"#,
352+
&["E0425"],
351353
);
352354
check_fix(
353355
r#"
@@ -376,7 +378,7 @@ fn test() {
376378

377379
#[test]
378380
fn remove_unnecessary_else_for_never() {
379-
check_diagnostics(
381+
check_diagnostics_with_disabled(
380382
r#"
381383
fn test() {
382384
if foo {
@@ -391,6 +393,7 @@ fn never() -> ! {
391393
loop {}
392394
}
393395
"#,
396+
&["E0425"],
394397
);
395398
check_fix(
396399
r#"
@@ -423,7 +426,7 @@ fn never() -> ! {
423426

424427
#[test]
425428
fn no_diagnostic_if_no_else_branch() {
426-
check_diagnostics(
429+
check_diagnostics_with_disabled(
427430
r#"
428431
fn test() {
429432
if foo {
@@ -433,12 +436,13 @@ fn test() {
433436
do_something_else();
434437
}
435438
"#,
439+
&["E0425"],
436440
);
437441
}
438442

439443
#[test]
440444
fn no_diagnostic_if_no_divergence() {
441-
check_diagnostics(
445+
check_diagnostics_with_disabled(
442446
r#"
443447
fn test() {
444448
if foo {
@@ -448,12 +452,13 @@ fn test() {
448452
}
449453
}
450454
"#,
455+
&["E0425"],
451456
);
452457
}
453458

454459
#[test]
455460
fn no_diagnostic_if_no_divergence_in_else_branch() {
456-
check_diagnostics_with_needless_return_disabled(
461+
check_diagnostics_with_disabled(
457462
r#"
458463
fn test() {
459464
if foo {
@@ -463,12 +468,13 @@ fn test() {
463468
}
464469
}
465470
"#,
471+
&["needless_return", "E0425"],
466472
);
467473
}
468474

469475
#[test]
470476
fn no_diagnostic_if_not_expr_stmt() {
471-
check_diagnostics_with_needless_return_disabled(
477+
check_diagnostics_with_disabled(
472478
r#"
473479
fn test1() {
474480
let _x = if a {
@@ -490,13 +496,15 @@ fn test2() {
490496
};
491497
}
492498
"#,
499+
&["needless_return", "E0425"],
493500
);
494-
check_diagnostics(
501+
check_diagnostics_with_disabled(
495502
r#"
496503
fn test3() -> u8 {
497504
foo(if a { return 1 } else { 0 })
498505
}
499506
"#,
507+
&["E0425"],
500508
);
501509
}
502510
}

crates/ide-diagnostics/src/handlers/type_mismatch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ fn f() -> i32 {
730730
}
731731
fn g() { return; }
732732
"#,
733-
std::iter::once("needless_return".to_owned()),
733+
&["needless_return"],
734734
);
735735
}
736736

0 commit comments

Comments
 (0)