Skip to content

Commit d9e95ea

Browse files
committed
Add `on_unimplemented" typo suggestions
1 parent ac385a5 commit d9e95ea

File tree

5 files changed

+72
-5
lines changed

5 files changed

+72
-5
lines changed

compiler/rustc_lint/src/context/diagnostics.rs

+8
Original file line numberDiff line numberDiff line change
@@ -347,5 +347,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
347347
"reduce the glob import's visibility or increase visibility of imported items",
348348
);
349349
}
350+
BuiltinLintDiag::MaybeTypo { span, name } => {
351+
diag.span_suggestion_verbose(
352+
span,
353+
"an attribute with a similar name exists",
354+
name,
355+
Applicability::MachineApplicable,
356+
);
357+
}
350358
}
351359
}

compiler/rustc_lint_defs/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,10 @@ pub enum BuiltinLintDiag {
663663
span: Span,
664664
max_vis: String,
665665
},
666+
MaybeTypo {
667+
span: Span,
668+
name: Symbol,
669+
},
666670
}
667671

668672
/// Lints that are buffered up early on in the `Session` before the

compiler/rustc_resolve/src/macros.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE};
2929
use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES};
3030
use rustc_session::lint::BuiltinLintDiag;
3131
use rustc_session::parse::feature_err;
32+
use rustc_span::edit_distance::edit_distance;
3233
use rustc_span::edition::Edition;
3334
use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
3435
use rustc_span::hygiene::{AstPass, MacroKind};
@@ -568,15 +569,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
568569
}
569570

570571
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
571-
&& path.segments.len() >= 2
572-
&& path.segments[0].ident.name == sym::diagnostic
573-
&& path.segments[1].ident.name != sym::on_unimplemented
572+
&& let [namespace, attribute, ..] = &*path.segments
573+
&& namespace.ident.name == sym::diagnostic
574+
&& attribute.ident.name != sym::on_unimplemented
574575
{
575-
self.tcx.sess.psess.buffer_lint(
576+
let distance =
577+
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
578+
579+
let help = if distance.is_some() {
580+
BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented }
581+
} else {
582+
BuiltinLintDiag::Normal
583+
};
584+
self.tcx.sess.psess.buffer_lint_with_diagnostic(
576585
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
577-
path.segments[1].span(),
586+
attribute.span(),
578587
node_id,
579588
"unknown diagnostic attribute",
589+
help,
580590
);
581591
}
582592

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![deny(unknown_or_malformed_diagnostic_attributes)]
2+
3+
#[diagnostic::onunimplemented]
4+
//~^ERROR unknown diagnostic attribute
5+
trait X{}
6+
7+
#[diagnostic::un_onimplemented]
8+
//~^ERROR unknown diagnostic attribute
9+
trait Y{}
10+
11+
#[diagnostic::on_implemented]
12+
//~^ERROR unknown diagnostic attribute
13+
trait Z{}
14+
15+
fn main(){}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error: unknown diagnostic attribute
2+
--> $DIR/suggest_typos.rs:3:15
3+
|
4+
LL | #[diagnostic::onunimplemented]
5+
| ^^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/suggest_typos.rs:1:9
9+
|
10+
LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
help: an attribute with a similar name exists
13+
|
14+
LL | #[diagnostic::on_unimplemented]
15+
| ~~~~~~~~~~~~~~~~
16+
17+
error: unknown diagnostic attribute
18+
--> $DIR/suggest_typos.rs:7:15
19+
|
20+
LL | #[diagnostic::un_onimplemented]
21+
| ^^^^^^^^^^^^^^^^
22+
23+
error: unknown diagnostic attribute
24+
--> $DIR/suggest_typos.rs:11:15
25+
|
26+
LL | #[diagnostic::on_implemented]
27+
| ^^^^^^^^^^^^^^
28+
29+
error: aborting due to 3 previous errors
30+

0 commit comments

Comments
 (0)