diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 6783415619f98..e6452ad09278e 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -422,6 +422,7 @@ pub enum BuiltinLintDiagnostics { ProcMacroDeriveResolutionFallback(Span), MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span, String), + UnknownCrateTypes(Span, String, String), } impl BuiltinLintDiagnostics { @@ -500,6 +501,14 @@ impl BuiltinLintDiagnostics { Applicability::MachineApplicable ); } + BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { + db.span_suggestion_with_applicability( + span, + ¬e, + sugg, + Applicability::MaybeIncorrect + ); + } } } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index d27b0856c1533..7fb66ea97f26b 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -57,6 +57,8 @@ use syntax::ext::base::ExtCtxt; use syntax::fold::Folder; use syntax::parse::{self, PResult}; use syntax::util::node_count::NodeCounter; +use syntax::util::lev_distance::find_best_match_for_name; +use syntax::symbol::Symbol; use syntax_pos::{FileName, hygiene}; use syntax_ext; @@ -1508,13 +1510,45 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Some(config::CrateType::Staticlib), Some(ref n) if *n == "proc-macro" => Some(config::CrateType::ProcMacro), Some(ref n) if *n == "bin" => Some(config::CrateType::Executable), - Some(_) => { - session.buffer_lint( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - a.span, - "invalid `crate_type` value", - ); + Some(ref n) => { + let crate_types = vec![ + Symbol::intern("rlib"), + Symbol::intern("dylib"), + Symbol::intern("cdylib"), + Symbol::intern("lib"), + Symbol::intern("staticlib"), + Symbol::intern("proc-macro"), + Symbol::intern("bin") + ]; + if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().node { + let span = spanned.span; + let lev_candidate = find_best_match_for_name( + crate_types.iter(), + &n.as_str(), + None + ); + if let Some(candidate) = lev_candidate { + session.buffer_lint_with_diagnostic( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value", + lint::builtin::BuiltinLintDiagnostics:: + UnknownCrateTypes( + span, + "did you mean".to_string(), + format!("\"{}\"", candidate) + ) + ); + } else { + session.buffer_lint( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value" + ); + } + } None } _ => { diff --git a/src/test/ui/invalid/invalid-crate-type.rs b/src/test/ui/invalid/invalid-crate-type.rs index 4b6b6c2fe7677..e7f4e32dc7c41 100644 --- a/src/test/ui/invalid/invalid-crate-type.rs +++ b/src/test/ui/invalid/invalid-crate-type.rs @@ -11,6 +11,48 @@ // regression test for issue 11256 #![crate_type="foo"] //~ ERROR invalid `crate_type` value +// Tests for suggestions (#53958) + +#![crate_type="statoclib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION staticlib + +#![crate_type="procmacro"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION proc-macro + +#![crate_type="static-lib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION staticlib + +#![crate_type="drylib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION dylib + +#![crate_type="dlib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION rlib + +#![crate_type="lob"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION lib + +#![crate_type="bon"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION bin + +#![crate_type="cdalib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION cdylib + fn main() { return } diff --git a/src/test/ui/invalid/invalid-crate-type.stderr b/src/test/ui/invalid/invalid-crate-type.stderr index 6dc8a0f2bbb04..c82da865f3353 100644 --- a/src/test/ui/invalid/invalid-crate-type.stderr +++ b/src/test/ui/invalid/invalid-crate-type.stderr @@ -1,10 +1,58 @@ error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:12:1 + --> $DIR/invalid-crate-type.rs:12:15 | LL | #![crate_type="foo"] //~ ERROR invalid `crate_type` value - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ | = note: #[deny(unknown_crate_types)] on by default -error: aborting due to previous error +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:16:15 + | +LL | #![crate_type="statoclib"] + | ^^^^^^^^^^^ help: did you mean: `"staticlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:21:15 + | +LL | #![crate_type="procmacro"] + | ^^^^^^^^^^^ help: did you mean: `"proc-macro"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:26:15 + | +LL | #![crate_type="static-lib"] + | ^^^^^^^^^^^^ help: did you mean: `"staticlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:31:15 + | +LL | #![crate_type="drylib"] + | ^^^^^^^^ help: did you mean: `"dylib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:36:15 + | +LL | #![crate_type="dlib"] + | ^^^^^^ help: did you mean: `"rlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:41:15 + | +LL | #![crate_type="lob"] + | ^^^^^ help: did you mean: `"lib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:46:15 + | +LL | #![crate_type="bon"] + | ^^^^^ help: did you mean: `"bin"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:51:15 + | +LL | #![crate_type="cdalib"] + | ^^^^^^^^ help: did you mean: `"cdylib"` + +error: aborting due to 9 previous errors