Rollup merge of #98624 - davidtwco:translation-on-lints, r=compiler-errors
lints: mostly translatable diagnostics As lints are created slightly differently than other diagnostics, intended to try make them translatable first and then look into the applicability of diagnostic structs but ended up just making most of the diagnostics in the crate translatable (which will still be useful if I do make a lot of them structs later anyway). r? ``@compiler-errors``
This commit is contained in:
commit
291df97fae
400
compiler/rustc_error_messages/locales/en-US/lint.ftl
Normal file
400
compiler/rustc_error_messages/locales/en-US/lint.ftl
Normal file
@ -0,0 +1,400 @@
|
||||
lint-array-into-iter =
|
||||
this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <{$target} as IntoIterator>::into_iter in Rust 2021
|
||||
.use-iter-suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
||||
.remove-into-iter-suggestion = or remove `.into_iter()` to iterate by value
|
||||
.use-explicit-into-iter-suggestion =
|
||||
or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
||||
|
||||
lint-enum-intrinsics-mem-discriminant =
|
||||
the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
.note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum.
|
||||
|
||||
lint-enum-intrinsics-mem-variant =
|
||||
the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
.note = the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum.
|
||||
|
||||
lint-expectation = this lint expectation is unfulfilled
|
||||
.note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
|
||||
lint-hidden-unicode-codepoints = unicode codepoint changing visible direction of text present in {$label}
|
||||
.label = this {$label} contains {$count ->
|
||||
[one] an invisible
|
||||
*[other] invisible
|
||||
} unicode text flow control {$count ->
|
||||
[one] codepoint
|
||||
*[other] codepoints
|
||||
}
|
||||
.note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
|
||||
.suggestion-remove = if their presence wasn't intentional, you can remove them
|
||||
.suggestion-escape = if you want to keep them but make them visible in your source code, you can escape them
|
||||
.no-suggestion-note-escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped}
|
||||
|
||||
lint-default-hash-types = prefer `{$preferred}` over `{$used}`, it has better performance
|
||||
.note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
|
||||
|
||||
lint-query-instability = using `{$query}` can result in unstable query results
|
||||
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||
|
||||
lint-tykind-kind = usage of `ty::TyKind::<kind>`
|
||||
.suggestion = try using `ty::<kind>` directly
|
||||
|
||||
lint-tykind = usage of `ty::TyKind`
|
||||
.help = try using `Ty` instead
|
||||
|
||||
lint-ty-qualified = usage of qualified `ty::{$ty}`
|
||||
.suggestion = try importing it and using it unqualified
|
||||
|
||||
lint-lintpass-by-hand = implementing `LintPass` by hand
|
||||
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
|
||||
|
||||
lint-non-existant-doc-keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = \"...\")]`
|
||||
.help = only existing keywords are allowed in core/std
|
||||
|
||||
lint-diag-out-of-impl =
|
||||
diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
|
||||
|
||||
lint-untranslatable-diag = diagnostics should be created using translatable messages
|
||||
|
||||
lint-cstring-ptr = getting the inner pointer of a temporary `CString`
|
||||
.as-ptr-label = this pointer will be invalid
|
||||
.unwrap-label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
||||
.note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
|
||||
.help = for more information, see https://doc.rust-lang.org/reference/destructors.html
|
||||
|
||||
lint-identifier-non-ascii-char = identifier contains non-ASCII characters
|
||||
|
||||
lint-identifier-uncommon-codepoints = identifier contains uncommon Unicode codepoints
|
||||
|
||||
lint-confusable-identifier-pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
|
||||
.label = this is where the previous identifier occurred
|
||||
|
||||
lint-mixed-script-confusables =
|
||||
the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
|
||||
.includes-note = the usage includes {$includes}
|
||||
.note = please recheck to make sure their usages are indeed what you want
|
||||
|
||||
lint-non-fmt-panic = panic message is not a string literal
|
||||
.note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021
|
||||
.more-info-note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
.supports-fmt-note = the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here
|
||||
.supports-fmt-suggestion = remove the `format!(..)` macro call
|
||||
.display-suggestion = add a "{"{"}{"}"}" format string to `Display` the message
|
||||
.debug-suggestion =
|
||||
add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}`
|
||||
.panic-suggestion = {$already_suggested ->
|
||||
[true] or use
|
||||
*[false] use
|
||||
} std::panic::panic_any instead
|
||||
|
||||
lint-non-fmt-panic-unused =
|
||||
panic message contains {$count ->
|
||||
[one] an unused
|
||||
*[other] unused
|
||||
} formatting {$count ->
|
||||
[one] placeholder
|
||||
*[other] placeholders
|
||||
}
|
||||
.note = this message is not used as a format string when given without arguments, but will be in Rust 2021
|
||||
.add-args-suggestion = add the missing {$count ->
|
||||
[one] argument
|
||||
*[other] arguments
|
||||
}
|
||||
.add-fmt-suggestion = or add a "{"{"}{"}"}" format string to use the message literally
|
||||
|
||||
lint-non-fmt-panic-braces =
|
||||
panic message contains {$count ->
|
||||
[one] a brace
|
||||
*[other] braces
|
||||
}
|
||||
.note = this message is not used as a format string, but will be in Rust 2021
|
||||
.suggestion = add a "{"{"}{"}"}" format string to use the message literally
|
||||
|
||||
lint-non-camel-case-type = {$sort} `{$name}` should have an upper camel case name
|
||||
.suggestion = convert the identifier to upper camel case
|
||||
.label = should have an UpperCamelCase name
|
||||
|
||||
lint-non-snake-case = {$sort} `{$name}` should have a snake case name
|
||||
.rename-or-convert-suggestion = rename the identifier or convert it to a snake case raw identifier
|
||||
.cannot-convert-note = `{$sc}` cannot be used as a raw identifier
|
||||
.rename-suggestion = rename the identifier
|
||||
.convert-suggestion = convert the identifier to snake case
|
||||
.help = convert the identifier to snake case: `{$sc}`
|
||||
.label = should have a snake_case name
|
||||
|
||||
lint-non-upper_case-global = {$sort} `{$name}` should have an upper case name
|
||||
.suggestion = convert the identifier to upper case
|
||||
.label = should have an UPPER_CASE name
|
||||
|
||||
lint-noop-method-call = call to `.{$method}()` on a reference in this situation does nothing
|
||||
.label = unnecessary method call
|
||||
.note = the type `{$receiver_ty}` which `{$method}` is being called on is the same as the type returned from `{$method}`, so the method call does not do anything and can be removed
|
||||
|
||||
lint-pass-by-value = passing `{$ty}` by reference
|
||||
.suggestion = try passing by value
|
||||
|
||||
lint-redundant-semicolons =
|
||||
unnecessary trailing {$multiple ->
|
||||
[true] semicolons
|
||||
*[false] semicolon
|
||||
}
|
||||
.suggestion = remove {$multiple ->
|
||||
[true] these semicolons
|
||||
*[false] this semicolon
|
||||
}
|
||||
|
||||
lint-drop-trait-constraints =
|
||||
bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
|
||||
|
||||
lint-drop-glue =
|
||||
types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
|
||||
|
||||
lint-range-endpoint-out-of-range = range endpoint is out of range for `{$ty}`
|
||||
.suggestion = use an inclusive range instead
|
||||
|
||||
lint-overflowing-bin-hex = literal out of range for `{$ty}`
|
||||
.negative-note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
|
||||
.negative-becomes-note = and the value `-{$lit}` will become `{$actually}{$ty}`
|
||||
.positive-note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`
|
||||
.suggestion = consider using the type `{$suggestion_ty}` instead
|
||||
.help = consider using the type `{$suggestion_ty}` instead
|
||||
|
||||
lint-overflowing-int = literal out of range for `{$ty}`
|
||||
.note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
|
||||
.help = consider using the type `{$suggestion_ty}` instead
|
||||
|
||||
lint-only-cast-u8-to-char = only `u8` can be cast into `char`
|
||||
.suggestion = use a `char` literal instead
|
||||
|
||||
lint-overflowing-uint = literal out of range for `{$ty}`
|
||||
.note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
|
||||
|
||||
lint-overflowing-literal = literal out of range for `{$ty}`
|
||||
.note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
|
||||
|
||||
lint-unused-comparisons = comparison is useless due to type limits
|
||||
|
||||
lint-improper-ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
|
||||
.label = not FFI-safe
|
||||
.note = the type is defined here
|
||||
|
||||
lint-improper-ctypes-opaque = opaque types have no C equivalent
|
||||
|
||||
lint-improper-ctypes-fnptr-reason = this function pointer has Rust-specific calling convention
|
||||
lint-improper-ctypes-fnptr-help = consider using an `extern fn(...) -> ...` function pointer instead
|
||||
|
||||
lint-improper-ctypes-tuple-reason = tuples have unspecified layout
|
||||
lint-improper-ctypes-tuple-help = consider using a struct instead
|
||||
|
||||
lint-improper-ctypes-str-reason = string slices have no C equivalent
|
||||
lint-improper-ctypes-str-help = consider using `*const u8` and a length instead
|
||||
|
||||
lint-improper-ctypes-dyn = trait objects have no C equivalent
|
||||
|
||||
lint-improper-ctypes-slice-reason = slices have no C equivalent
|
||||
lint-improper-ctypes-slice-help = consider using a raw pointer instead
|
||||
|
||||
lint-improper-ctypes-128bit = 128-bit integers don't currently have a known stable ABI
|
||||
|
||||
lint-improper-ctypes-char-reason = the `char` type has no C equivalent
|
||||
lint-improper-ctypes-char-help = consider using `u32` or `libc::wchar_t` instead
|
||||
|
||||
lint-improper-ctypes-non-exhaustive = this enum is non-exhaustive
|
||||
lint-improper-ctypes-non-exhaustive-variant = this enum has non-exhaustive variants
|
||||
|
||||
lint-improper-ctypes-enum-repr-reason = enum has no representation hint
|
||||
lint-improper-ctypes-enum-repr-help =
|
||||
consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
|
||||
|
||||
lint-improper-ctypes-struct-fieldless-reason = this struct has no fields
|
||||
lint-improper-ctypes-struct-fieldless-help = consider adding a member to this struct
|
||||
|
||||
lint-improper-ctypes-union-fieldless-reason = this union has no fields
|
||||
lint-improper-ctypes-union-fieldless-help = consider adding a member to this union
|
||||
|
||||
lint-improper-ctypes-struct-non-exhaustive = this struct is non-exhaustive
|
||||
lint-improper-ctypes-union-non-exhaustive = this union is non-exhaustive
|
||||
|
||||
lint-improper-ctypes-struct-layout-reason = this struct has unspecified layout
|
||||
lint-improper-ctypes-struct-layout-help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
|
||||
|
||||
lint-improper-ctypes-union-layout-reason = this union has unspecified layout
|
||||
lint-improper-ctypes-union-layout-help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
|
||||
|
||||
lint-improper-ctypes-box = box cannot be represented as a single pointer
|
||||
|
||||
lint-improper-ctypes-enum-phantomdata = this enum contains a PhantomData field
|
||||
|
||||
lint-improper-ctypes-struct-zst = this struct contains only zero-sized fields
|
||||
|
||||
lint-improper-ctypes-array-reason = passing raw arrays by value is not FFI-safe
|
||||
lint-improper-ctypes-array-help = consider passing a pointer to the array
|
||||
|
||||
lint-improper-ctypes-only-phantomdata = composed only of `PhantomData`
|
||||
|
||||
lint-variant-size-differences =
|
||||
enum variant is more than three times larger ({$largest} bytes) than the next largest
|
||||
|
||||
lint-atomic-ordering-load = atomic loads cannot have `Release` or `AcqRel` ordering
|
||||
.help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
|
||||
|
||||
lint-atomic-ordering-store = atomic stores cannot have `Acquire` or `AcqRel` ordering
|
||||
.help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
|
||||
|
||||
lint-atomic-ordering-fence = memory fences cannot have `Relaxed` ordering
|
||||
.help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
|
||||
|
||||
lint-atomic-ordering-invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
|
||||
.label = invalid failure ordering
|
||||
.help = consider using `Acquire` or `Relaxed` failure ordering instead
|
||||
|
||||
lint-atomic-ordering-invalid-fail-success = `{$method}`'s success ordering must be at least as strong as its failure ordering
|
||||
.fail-label = `{$fail_ordering}` failure ordering
|
||||
.success-label = `{$success_ordering}` success ordering
|
||||
.suggestion = consider using `{$success_suggestion}` success ordering instead
|
||||
|
||||
lint-unused-op = unused {$op} that must be used
|
||||
.label = the {$op} produces a value
|
||||
.suggestion = use `let _ = ...` to ignore the resulting value
|
||||
|
||||
lint-unused-result = unused result of type `{$ty}`
|
||||
|
||||
lint-unused-closure =
|
||||
unused {$pre}{$count ->
|
||||
[one] closure
|
||||
*[other] closures
|
||||
}{$post} that must be used
|
||||
.note = closures are lazy and do nothing unless called
|
||||
|
||||
lint-unused-generator =
|
||||
unused {$pre}{$count ->
|
||||
[one] generator
|
||||
*[other] generator
|
||||
}{$post} that must be used
|
||||
.note = generators are lazy and do nothing unless resumed
|
||||
|
||||
lint-unused-def = unused {$pre}`{$def}`{$post} that must be used
|
||||
|
||||
lint-path-statement-drop = path statement drops value
|
||||
.suggestion = use `drop` to clarify the intent
|
||||
|
||||
lint-path-statement-no-effect = path statement with no effect
|
||||
|
||||
lint-unused-delim = unnecessary {$delim} around {$item}
|
||||
.suggestion = remove these {$delim}
|
||||
|
||||
lint-unused-import-braces = braces around {$node} is unnecessary
|
||||
|
||||
lint-unused-allocation = unnecessary allocation, use `&` instead
|
||||
lint-unused-allocation-mut = unnecessary allocation, use `&mut` instead
|
||||
|
||||
lint-builtin-while-true = denote infinite loops with `loop {"{"} ... {"}"}`
|
||||
.suggestion = use `loop`
|
||||
|
||||
lint-builtin-box-pointers = type uses owned (Box type) pointers: {$ty}
|
||||
|
||||
lint-builtin-non-shorthand-field-patterns = the `{$ident}:` in this pattern is redundant
|
||||
.suggestion = use shorthand field pattern
|
||||
|
||||
lint-builtin-overridden-symbol-name =
|
||||
the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
|
||||
|
||||
lint-builtin-overridden-symbol-section =
|
||||
the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
|
||||
|
||||
lint-builtin-allow-internal-unsafe =
|
||||
`allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
|
||||
|
||||
lint-builtin-unsafe-block = usage of an `unsafe` block
|
||||
|
||||
lint-builtin-unsafe-trait = declaration of an `unsafe` trait
|
||||
|
||||
lint-builtin-unsafe-impl = implementation of an `unsafe` trait
|
||||
|
||||
lint-builtin-no-mangle-fn = declaration of a `no_mangle` function
|
||||
lint-builtin-export-name-fn = declaration of a function with `export_name`
|
||||
lint-builtin-link-section-fn = declaration of a function with `link_section`
|
||||
|
||||
lint-builtin-no-mangle-static = declaration of a `no_mangle` static
|
||||
lint-builtin-export-name-static = declaration of a static with `export_name`
|
||||
lint-builtin-link-section-static = declaration of a static with `link_section`
|
||||
|
||||
lint-builtin-no-mangle-method = declaration of a `no_mangle` method
|
||||
lint-builtin-export-name-method = declaration of a method with `export_name`
|
||||
|
||||
lint-builtin-decl-unsafe-fn = declaration of an `unsafe` function
|
||||
lint-builtin-decl-unsafe-method = declaration of an `unsafe` method
|
||||
lint-builtin-impl-unsafe-method = implementation of an `unsafe` method
|
||||
|
||||
lint-builtin-missing-doc = missing documentation for {$article} {$desc}
|
||||
|
||||
lint-builtin-missing-copy-impl = type could implement `Copy`; consider adding `impl Copy`
|
||||
|
||||
lint-builtin-missing-debug-impl =
|
||||
type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation
|
||||
|
||||
lint-builtin-anonymous-params = anonymous parameters are deprecated and will be removed in the next edition
|
||||
.suggestion = try naming the parameter or explicitly ignoring it
|
||||
|
||||
lint-builtin-deprecated-attr-link = use of deprecated attribute `{$name}`: {$reason}. See {$link}
|
||||
lint-builtin-deprecated-attr-used = use of deprecated attribute `{$name}`: no longer used.
|
||||
lint-builtin-deprecated-attr-default-suggestion = remove this attribute
|
||||
|
||||
lint-builtin-unused-doc-comment = unused doc comment
|
||||
.label = rustdoc does not generate documentation for {$kind}
|
||||
.plain-help = use `//` for a plain comment
|
||||
.block-help = use `/* */` for a plain comment
|
||||
|
||||
lint-builtin-no-mangle-generic = functions generic over types or consts must be mangled
|
||||
.suggestion = remove this attribute
|
||||
|
||||
lint-builtin-const-no-mangle = const items should never be `#[no_mangle]`
|
||||
.suggestion = try a static value
|
||||
|
||||
lint-builtin-mutable-transmutes =
|
||||
transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
|
||||
|
||||
lint-builtin-unstable-features = unstable feature
|
||||
|
||||
lint-builtin-unreachable-pub = unreachable `pub` {$what}
|
||||
.suggestion = consider restricting its visibility
|
||||
.help = or consider exporting it for use by other crates
|
||||
|
||||
lint-builtin-type-alias-bounds-help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
|
||||
|
||||
lint-builtin-type-alias-where-clause = where clauses are not enforced in type aliases
|
||||
.suggestion = the clause will not be checked when the type alias is used, and should be removed
|
||||
|
||||
lint-builtin-type-alias-generic-bounds = bounds on generic parameters are not enforced in type aliases
|
||||
.suggestion = the bound will not be checked when the type alias is used, and should be removed
|
||||
|
||||
lint-builtin-trivial-bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
|
||||
|
||||
lint-builtin-ellipsis-inclusive-range-patterns = `...` range patterns are deprecated
|
||||
.suggestion = use `..=` for an inclusive range
|
||||
|
||||
lint-builtin-unnameable-test-items = cannot test inner items
|
||||
|
||||
lint-builtin-keyword-idents = `{$kw}` is a keyword in the {$next} edition
|
||||
.suggestion = you can use a raw identifier to stay compatible
|
||||
|
||||
lint-builtin-explicit-outlives = outlives requirements can be inferred
|
||||
.suggestion = remove {$count ->
|
||||
[one] this bound
|
||||
*[other] these bounds
|
||||
}
|
||||
|
||||
lint-builtin-incomplete-features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
.note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
|
||||
.help = consider using `min_{$name}` instead, which is more stable and complete
|
||||
|
||||
lint-builtin-clashing-extern-same-name = `{$this_fi}` redeclared with a different signature
|
||||
.previous-decl-label = `{$orig}` previously declared here
|
||||
.mismatch-label = this signature doesn't match the previous declaration
|
||||
lint-builtin-clashing-extern-diff-name = `{$this_fi}` redeclares `{$orig}` with a different signature
|
||||
.previous-decl-label = `{$orig}` previously declared here
|
||||
.mismatch-label = this signature doesn't match the previous declaration
|
||||
|
||||
lint-builtin-deref-nullptr = dereferencing a null pointer
|
||||
.label = this code causes undefined behavior when executed
|
||||
|
||||
lint-builtin-asm-labels = avoid using named labels in inline assembly
|
@ -31,11 +31,12 @@ pub use unic_langid::{langid, LanguageIdentifier};
|
||||
|
||||
// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
|
||||
fluent_messages! {
|
||||
borrowck => "../locales/en-US/borrowck.ftl",
|
||||
builtin_macros => "../locales/en-US/builtin_macros.ftl",
|
||||
lint => "../locales/en-US/lint.ftl",
|
||||
parser => "../locales/en-US/parser.ftl",
|
||||
privacy => "../locales/en-US/privacy.ftl",
|
||||
typeck => "../locales/en-US/typeck.ftl",
|
||||
builtin_macros => "../locales/en-US/builtin_macros.ftl",
|
||||
borrowck => "../locales/en-US/borrowck.ftl",
|
||||
}
|
||||
|
||||
pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES};
|
||||
|
@ -8,7 +8,7 @@ use rustc_error_messages::FluentValue;
|
||||
use rustc_lint_defs::{Applicability, LintExpectationId};
|
||||
use rustc_span::edition::LATEST_STABLE_EDITION;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::{edition::Edition, Span, DUMMY_SP};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
@ -39,12 +39,94 @@ pub trait IntoDiagnosticArg {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>;
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for bool {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
if self {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed("true"))
|
||||
} else {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed("false"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for i8 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for u8 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for i16 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for u16 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for i32 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for u32 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for i64 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for u64 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for i128 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for u128 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for String {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for std::num::NonZeroU32 {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for Edition {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for Symbol {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
self.to_ident_string().into_diagnostic_arg()
|
||||
|
@ -529,7 +529,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn set_primary_message(&mut self, msg: impl Into<String>) -> &mut Self);
|
||||
forward!(pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn set_span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self);
|
||||
forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
|
||||
forward!(pub fn set_arg(
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{fluent, Applicability};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
|
||||
@ -120,31 +120,30 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
|
||||
_ => bug!("array type coerced to something other than array or slice"),
|
||||
};
|
||||
cx.struct_span_lint(ARRAY_INTO_ITER, call.ident.span, |lint| {
|
||||
let mut diag = lint.build(&format!(
|
||||
"this method call resolves to `<&{} as IntoIterator>::into_iter` \
|
||||
(due to backwards compatibility), \
|
||||
but will resolve to <{} as IntoIterator>::into_iter in Rust 2021",
|
||||
target, target,
|
||||
));
|
||||
let mut diag = lint.build(fluent::lint::array_into_iter);
|
||||
diag.set_arg("target", target);
|
||||
diag.span_suggestion(
|
||||
call.ident.span,
|
||||
"use `.iter()` instead of `.into_iter()` to avoid ambiguity",
|
||||
fluent::lint::use_iter_suggestion,
|
||||
"iter",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if self.for_expr_span == expr.span {
|
||||
diag.span_suggestion(
|
||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
"or remove `.into_iter()` to iterate by value",
|
||||
fluent::lint::remove_into_iter_suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else if receiver_ty.is_array() {
|
||||
diag.multipart_suggestion(
|
||||
"or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value",
|
||||
fluent::lint::use_explicit_into_iter_suggestion,
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
|
||||
(receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()),
|
||||
(
|
||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
")".into(),
|
||||
),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
@ -31,7 +31,9 @@ use rustc_ast::{self as ast, *};
|
||||
use rustc_ast_pretty::pprust::{self, expr_to_string};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticStyledString, MultiSpan};
|
||||
use rustc_errors::{
|
||||
fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, MultiSpan,
|
||||
};
|
||||
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
@ -99,13 +101,12 @@ impl EarlyLintPass for WhileTrue {
|
||||
if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
|
||||
if let ast::LitKind::Bool(true) = lit.kind {
|
||||
if !lit.span.from_expansion() {
|
||||
let msg = "denote infinite loops with `loop { ... }`";
|
||||
let condition_span = e.span.with_hi(cond.span.hi());
|
||||
cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
|
||||
lint.build(msg)
|
||||
lint.build(fluent::lint::builtin_while_true)
|
||||
.span_suggestion_short(
|
||||
condition_span,
|
||||
"use `loop`",
|
||||
fluent::lint::suggestion,
|
||||
format!(
|
||||
"{}loop",
|
||||
label.map_or_else(String::new, |label| format!(
|
||||
@ -156,7 +157,7 @@ impl BoxPointers {
|
||||
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
|
||||
if leaf_ty.is_box() {
|
||||
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
|
||||
lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit();
|
||||
lint.build(fluent::lint::builtin_box_pointers).set_arg("ty", ty).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -257,26 +258,26 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
|
||||
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
|
||||
{
|
||||
cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| {
|
||||
let mut err = lint
|
||||
.build(&format!("the `{}:` in this pattern is redundant", ident));
|
||||
let binding = match binding_annot {
|
||||
hir::BindingAnnotation::Unannotated => None,
|
||||
hir::BindingAnnotation::Mutable => Some("mut"),
|
||||
hir::BindingAnnotation::Ref => Some("ref"),
|
||||
hir::BindingAnnotation::RefMut => Some("ref mut"),
|
||||
};
|
||||
let ident = if let Some(binding) = binding {
|
||||
let suggested_ident = if let Some(binding) = binding {
|
||||
format!("{} {}", binding, ident)
|
||||
} else {
|
||||
ident.to_string()
|
||||
};
|
||||
err.span_suggestion(
|
||||
fieldpat.span,
|
||||
"use shorthand field pattern",
|
||||
ident,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
lint.build(fluent::lint::builtin_non_shorthand_field_patterns)
|
||||
.set_arg("ident", ident.clone())
|
||||
.span_suggestion(
|
||||
fieldpat.span,
|
||||
fluent::lint::suggestion,
|
||||
suggested_ident,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -327,26 +328,25 @@ impl UnsafeCode {
|
||||
cx.struct_span_lint(UNSAFE_CODE, span, decorate);
|
||||
}
|
||||
|
||||
fn report_overridden_symbol_name(&self, cx: &EarlyContext<'_>, span: Span, msg: &str) {
|
||||
fn report_overridden_symbol_name(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
span: Span,
|
||||
msg: DiagnosticMessage,
|
||||
) {
|
||||
self.report_unsafe(cx, span, |lint| {
|
||||
lint.build(msg)
|
||||
.note(
|
||||
"the linker's behavior with multiple libraries exporting duplicate symbol \
|
||||
names is undefined and Rust cannot provide guarantees when you manually \
|
||||
override them",
|
||||
)
|
||||
.emit();
|
||||
lint.build(msg).note(fluent::lint::builtin_overridden_symbol_name).emit();
|
||||
})
|
||||
}
|
||||
|
||||
fn report_overridden_symbol_section(&self, cx: &EarlyContext<'_>, span: Span, msg: &str) {
|
||||
fn report_overridden_symbol_section(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
span: Span,
|
||||
msg: DiagnosticMessage,
|
||||
) {
|
||||
self.report_unsafe(cx, span, |lint| {
|
||||
lint.build(msg)
|
||||
.note(
|
||||
"the program's behavior with overridden link sections on items is unpredictable \
|
||||
and Rust cannot provide guarantees when you manually override them",
|
||||
)
|
||||
.emit();
|
||||
lint.build(msg).note(fluent::lint::builtin_overridden_symbol_section).emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -355,12 +355,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||
if attr.has_name(sym::allow_internal_unsafe) {
|
||||
self.report_unsafe(cx, attr.span, |lint| {
|
||||
lint.build(
|
||||
"`allow_internal_unsafe` allows defining \
|
||||
macros using unsafe without triggering \
|
||||
the `unsafe_code` lint at their call site",
|
||||
)
|
||||
.emit();
|
||||
lint.build(fluent::lint::builtin_allow_internal_unsafe).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -370,7 +365,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
// Don't warn about generated blocks; that'll just pollute the output.
|
||||
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
|
||||
self.report_unsafe(cx, blk.span, |lint| {
|
||||
lint.build("usage of an `unsafe` block").emit();
|
||||
lint.build(fluent::lint::builtin_unsafe_block).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -380,12 +375,12 @@ impl EarlyLintPass for UnsafeCode {
|
||||
match it.kind {
|
||||
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
||||
.report_unsafe(cx, it.span, |lint| {
|
||||
lint.build("declaration of an `unsafe` trait").emit();
|
||||
lint.build(fluent::lint::builtin_unsafe_trait).emit();
|
||||
}),
|
||||
|
||||
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
||||
.report_unsafe(cx, it.span, |lint| {
|
||||
lint.build("implementation of an `unsafe` trait").emit();
|
||||
lint.build(fluent::lint::builtin_unsafe_impl).emit();
|
||||
}),
|
||||
|
||||
ast::ItemKind::Fn(..) => {
|
||||
@ -393,7 +388,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
self.report_overridden_symbol_name(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a `no_mangle` function",
|
||||
fluent::lint::builtin_no_mangle_fn,
|
||||
);
|
||||
}
|
||||
|
||||
@ -401,7 +396,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
self.report_overridden_symbol_name(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a function with `export_name`",
|
||||
fluent::lint::builtin_export_name_fn,
|
||||
);
|
||||
}
|
||||
|
||||
@ -409,7 +404,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
self.report_overridden_symbol_section(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a function with `link_section`",
|
||||
fluent::lint::builtin_link_section_fn,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -419,7 +414,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
self.report_overridden_symbol_name(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a `no_mangle` static",
|
||||
fluent::lint::builtin_no_mangle_static,
|
||||
);
|
||||
}
|
||||
|
||||
@ -427,7 +422,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
self.report_overridden_symbol_name(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a static with `export_name`",
|
||||
fluent::lint::builtin_export_name_static,
|
||||
);
|
||||
}
|
||||
|
||||
@ -435,7 +430,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||
self.report_overridden_symbol_section(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a static with `link_section`",
|
||||
fluent::lint::builtin_link_section_static,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -450,14 +445,14 @@ impl EarlyLintPass for UnsafeCode {
|
||||
self.report_overridden_symbol_name(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a `no_mangle` method",
|
||||
fluent::lint::builtin_no_mangle_method,
|
||||
);
|
||||
}
|
||||
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
|
||||
self.report_overridden_symbol_name(
|
||||
cx,
|
||||
attr.span,
|
||||
"declaration of a method with `export_name`",
|
||||
fluent::lint::builtin_export_name_method,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -475,9 +470,9 @@ impl EarlyLintPass for UnsafeCode {
|
||||
{
|
||||
let msg = match ctxt {
|
||||
FnCtxt::Foreign => return,
|
||||
FnCtxt::Free => "declaration of an `unsafe` function",
|
||||
FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method",
|
||||
FnCtxt::Assoc(_) => "implementation of an `unsafe` method",
|
||||
FnCtxt::Free => fluent::lint::builtin_decl_unsafe_fn,
|
||||
FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method,
|
||||
FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method,
|
||||
};
|
||||
self.report_unsafe(cx, span, |lint| {
|
||||
lint.build(msg).emit();
|
||||
@ -587,7 +582,10 @@ impl MissingDoc {
|
||||
MISSING_DOCS,
|
||||
cx.tcx.sess.source_map().guess_head_span(sp),
|
||||
|lint| {
|
||||
lint.build(&format!("missing documentation for {} {}", article, desc)).emit();
|
||||
lint.build(fluent::lint::builtin_missing_doc)
|
||||
.set_arg("article", article)
|
||||
.set_arg("desc", desc)
|
||||
.emit();
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -783,11 +781,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
||||
.is_ok()
|
||||
{
|
||||
cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
|
||||
lint.build(
|
||||
"type could implement `Copy`; consider adding `impl \
|
||||
Copy`",
|
||||
)
|
||||
.emit();
|
||||
lint.build(fluent::lint::builtin_missing_copy_impl).emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -863,12 +857,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
|
||||
|
||||
if !self.impling_types.as_ref().unwrap().contains(&item.def_id) {
|
||||
cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| {
|
||||
lint.build(&format!(
|
||||
"type does not implement `{}`; consider adding `#[derive(Debug)]` \
|
||||
or a manual implementation",
|
||||
cx.tcx.def_path_str(debug)
|
||||
))
|
||||
.emit();
|
||||
lint.build(fluent::lint::builtin_missing_debug_impl)
|
||||
.set_arg("debug", cx.tcx.def_path_str(debug))
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -946,18 +937,14 @@ impl EarlyLintPass for AnonymousParameters {
|
||||
("<type>", Applicability::HasPlaceholders)
|
||||
};
|
||||
|
||||
lint.build(
|
||||
"anonymous parameters are deprecated and will be \
|
||||
removed in the next edition",
|
||||
)
|
||||
.span_suggestion(
|
||||
arg.pat.span,
|
||||
"try naming the parameter or explicitly \
|
||||
ignoring it",
|
||||
format!("_: {}", ty_snip),
|
||||
appl,
|
||||
)
|
||||
.emit();
|
||||
lint.build(fluent::lint::builtin_anonymous_params)
|
||||
.span_suggestion(
|
||||
arg.pat.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("_: {}", ty_snip),
|
||||
appl,
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -982,24 +969,6 @@ impl DeprecatedAttr {
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_deprecated_attr(
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &ast::Attribute,
|
||||
msg: &str,
|
||||
suggestion: Option<&str>,
|
||||
) {
|
||||
cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
|
||||
lint.build(msg)
|
||||
.span_suggestion_short(
|
||||
attr.span,
|
||||
suggestion.unwrap_or("remove this attribute"),
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
}
|
||||
|
||||
impl EarlyLintPass for DeprecatedAttr {
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||
for BuiltinAttribute { name, gate, .. } in &self.depr_attrs {
|
||||
@ -1011,17 +980,38 @@ impl EarlyLintPass for DeprecatedAttr {
|
||||
_,
|
||||
) = gate
|
||||
{
|
||||
let msg =
|
||||
format!("use of deprecated attribute `{}`: {}. See {}", name, reason, link);
|
||||
lint_deprecated_attr(cx, attr, &msg, suggestion);
|
||||
cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
|
||||
// FIXME(davidtwco) translatable deprecated attr
|
||||
lint.build(fluent::lint::builtin_deprecated_attr_link)
|
||||
.set_arg("name", name)
|
||||
.set_arg("reason", reason)
|
||||
.set_arg("link", link)
|
||||
.span_suggestion_short(
|
||||
attr.span,
|
||||
suggestion.map(|s| s.into()).unwrap_or(
|
||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||
),
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
|
||||
let path_str = pprust::path_to_string(&attr.get_normal_item().path);
|
||||
let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str);
|
||||
lint_deprecated_attr(cx, attr, &msg, None);
|
||||
cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
|
||||
lint.build(fluent::lint::builtin_deprecated_attr_used)
|
||||
.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
|
||||
.span_suggestion_short(
|
||||
attr.span,
|
||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1049,17 +1039,15 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
|
||||
|
||||
if is_doc_comment || attr.has_name(sym::doc) {
|
||||
cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
|
||||
let mut err = lint.build("unused doc comment");
|
||||
err.span_label(
|
||||
node_span,
|
||||
format!("rustdoc does not generate documentation for {}", node_kind),
|
||||
);
|
||||
let mut err = lint.build(fluent::lint::builtin_unused_doc_comment);
|
||||
err.set_arg("kind", node_kind);
|
||||
err.span_label(node_span, fluent::lint::label);
|
||||
match attr.kind {
|
||||
AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
|
||||
err.help("use `//` for a plain comment");
|
||||
err.help(fluent::lint::plain_help);
|
||||
}
|
||||
AttrKind::DocComment(CommentKind::Block, _) => {
|
||||
err.help("use `/* */` for a plain comment");
|
||||
err.help(fluent::lint::block_help);
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
@ -1178,10 +1166,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
||||
cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| {
|
||||
lint.build("functions generic over types or consts must be mangled")
|
||||
lint.build(fluent::lint::builtin_no_mangle_generic)
|
||||
.span_suggestion_short(
|
||||
no_mangle_attr.span,
|
||||
"remove this attribute",
|
||||
fluent::lint::suggestion,
|
||||
"",
|
||||
// Use of `#[no_mangle]` suggests FFI intent; correct
|
||||
// fix may be to monomorphize source by hand
|
||||
@ -1205,8 +1193,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
||||
// Const items do not refer to a particular location in memory, and therefore
|
||||
// don't have anything to attach a symbol to
|
||||
cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| {
|
||||
let msg = "const items should never be `#[no_mangle]`";
|
||||
let mut err = lint.build(msg);
|
||||
let mut err = lint.build(fluent::lint::builtin_const_no_mangle);
|
||||
|
||||
// account for "pub const" (#45562)
|
||||
let start = cx
|
||||
@ -1220,7 +1207,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
||||
let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
|
||||
err.span_suggestion(
|
||||
const_span,
|
||||
"try a static value",
|
||||
fluent::lint::suggestion,
|
||||
"pub static",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
@ -1285,10 +1272,8 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
||||
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
|
||||
{
|
||||
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
||||
let msg = "transmuting &T to &mut T is undefined behavior, \
|
||||
even if the reference is unused, consider instead using an UnsafeCell";
|
||||
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
|
||||
lint.build(msg).emit();
|
||||
lint.build(fluent::lint::builtin_mutable_transmutes).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1338,7 +1323,7 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
for item in items {
|
||||
cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
|
||||
lint.build("unstable feature").emit();
|
||||
lint.build(fluent::lint::builtin_unstable_features).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1400,16 +1385,17 @@ impl UnreachablePub {
|
||||
}
|
||||
let def_span = cx.tcx.sess.source_map().guess_head_span(span);
|
||||
cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
|
||||
let mut err = lint.build(&format!("unreachable `pub` {}", what));
|
||||
let mut err = lint.build(fluent::lint::builtin_unreachable_pub);
|
||||
err.set_arg("what", what);
|
||||
|
||||
err.span_suggestion(
|
||||
vis_span,
|
||||
"consider restricting its visibility",
|
||||
fluent::lint::suggestion,
|
||||
"pub(crate)",
|
||||
applicability,
|
||||
);
|
||||
if exportable {
|
||||
err.help("or consider exporting it for use by other crates");
|
||||
err.help(fluent::lint::help);
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
@ -1513,11 +1499,7 @@ impl TypeAliasBounds {
|
||||
impl Visitor<'_> for WalkAssocTypes<'_> {
|
||||
fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) {
|
||||
if TypeAliasBounds::is_type_variable_assoc(qpath) {
|
||||
self.err.span_help(
|
||||
span,
|
||||
"use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to \
|
||||
associated types in type aliases",
|
||||
);
|
||||
self.err.span_help(span, fluent::lint::builtin_type_alias_bounds_help);
|
||||
}
|
||||
intravisit::walk_qpath(self, qpath, id, span)
|
||||
}
|
||||
@ -1561,11 +1543,11 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
||||
let mut suggested_changing_assoc_types = false;
|
||||
if !where_spans.is_empty() {
|
||||
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
|
||||
let mut err = lint.build("where clauses are not enforced in type aliases");
|
||||
let mut err = lint.build(fluent::lint::builtin_type_alias_where_clause);
|
||||
err.set_span(where_spans);
|
||||
err.span_suggestion(
|
||||
type_alias_generics.where_clause_span,
|
||||
"the clause will not be checked when the type alias is used, and should be removed",
|
||||
fluent::lint::suggestion,
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
@ -1579,11 +1561,10 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
||||
|
||||
if !inline_spans.is_empty() {
|
||||
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
|
||||
let mut err =
|
||||
lint.build("bounds on generic parameters are not enforced in type aliases");
|
||||
let mut err = lint.build(fluent::lint::builtin_type_alias_generic_bounds);
|
||||
err.set_span(inline_spans);
|
||||
err.multipart_suggestion(
|
||||
"the bound will not be checked when the type alias is used, and should be removed",
|
||||
fluent::lint::suggestion,
|
||||
inline_sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
@ -1690,12 +1671,10 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
|
||||
};
|
||||
if predicate.is_global() {
|
||||
cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
|
||||
lint.build(&format!(
|
||||
"{} bound {} does not depend on any type \
|
||||
or lifetime parameters",
|
||||
predicate_kind_name, predicate
|
||||
))
|
||||
.emit();
|
||||
lint.build(fluent::lint::builtin_trivial_bounds)
|
||||
.set_arg("predicate_kind_name", predicate_kind_name)
|
||||
.set_arg("predicate", predicate)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1796,8 +1775,8 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
||||
};
|
||||
|
||||
if let Some((start, end, join)) = endpoints {
|
||||
let msg = "`...` range patterns are deprecated";
|
||||
let suggestion = "use `..=` for an inclusive range";
|
||||
let msg = fluent::lint::builtin_ellipsis_inclusive_range_patterns;
|
||||
let suggestion = fluent::lint::suggestion;
|
||||
if parenthesise {
|
||||
self.node_id = Some(pat.id);
|
||||
let end = expr_to_string(&end);
|
||||
@ -1806,8 +1785,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
||||
None => format!("&(..={})", end),
|
||||
};
|
||||
if join.edition() >= Edition::Edition2021 {
|
||||
let mut err =
|
||||
rustc_errors::struct_span_err!(cx.sess(), pat.span, E0783, "{}", msg,);
|
||||
let mut err = cx.sess().struct_span_err_with_code(
|
||||
pat.span,
|
||||
msg,
|
||||
rustc_errors::error_code!(E0783),
|
||||
);
|
||||
err.span_suggestion(
|
||||
pat.span,
|
||||
suggestion,
|
||||
@ -1830,8 +1812,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
||||
} else {
|
||||
let replace = "..=";
|
||||
if join.edition() >= Edition::Edition2021 {
|
||||
let mut err =
|
||||
rustc_errors::struct_span_err!(cx.sess(), pat.span, E0783, "{}", msg,);
|
||||
let mut err = cx.sess().struct_span_err_with_code(
|
||||
pat.span,
|
||||
msg,
|
||||
rustc_errors::error_code!(E0783),
|
||||
);
|
||||
err.span_suggestion_short(
|
||||
join,
|
||||
suggestion,
|
||||
@ -1930,7 +1915,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
|
||||
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
||||
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
|
||||
cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
|
||||
lint.build("cannot test inner items").emit();
|
||||
lint.build(fluent::lint::builtin_unnameable_test_items).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -2048,10 +2033,12 @@ impl KeywordIdents {
|
||||
}
|
||||
|
||||
cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| {
|
||||
lint.build(&format!("`{}` is a keyword in the {} edition", ident, next_edition))
|
||||
lint.build(fluent::lint::builtin_keyword_idents)
|
||||
.set_arg("kw", ident.clone())
|
||||
.set_arg("next", next_edition)
|
||||
.span_suggestion(
|
||||
ident.span,
|
||||
"you can use a raw identifier to stay compatible",
|
||||
fluent::lint::suggestion,
|
||||
format!("r#{}", ident),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
@ -2301,13 +2288,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
||||
|
||||
if !lint_spans.is_empty() {
|
||||
cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| {
|
||||
lint.build("outlives requirements can be inferred")
|
||||
lint.build(fluent::lint::builtin_explicit_outlives)
|
||||
.set_arg("count", bound_count)
|
||||
.multipart_suggestion(
|
||||
if bound_count == 1 {
|
||||
"remove this bound"
|
||||
} else {
|
||||
"remove these bounds"
|
||||
},
|
||||
fluent::lint::suggestion,
|
||||
lint_spans
|
||||
.into_iter()
|
||||
.map(|span| (span, String::new()))
|
||||
@ -2363,23 +2347,14 @@ impl EarlyLintPass for IncompleteFeatures {
|
||||
.filter(|(&name, _)| features.incomplete(name))
|
||||
.for_each(|(&name, &span)| {
|
||||
cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| {
|
||||
let mut builder = lint.build(&format!(
|
||||
"the feature `{}` is incomplete and may not be safe to use \
|
||||
and/or cause compiler crashes",
|
||||
name,
|
||||
));
|
||||
let mut builder = lint.build(fluent::lint::builtin_incomplete_features);
|
||||
builder.set_arg("name", name);
|
||||
if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) {
|
||||
builder.note(&format!(
|
||||
"see issue #{} <https://github.com/rust-lang/rust/issues/{}> \
|
||||
for more information",
|
||||
n, n,
|
||||
));
|
||||
builder.set_arg("n", n);
|
||||
builder.note(fluent::lint::note);
|
||||
}
|
||||
if HAS_MIN_FEATURES.contains(&name) {
|
||||
builder.help(&format!(
|
||||
"consider using `min_{}` instead, which is more stable and complete",
|
||||
name,
|
||||
));
|
||||
builder.help(fluent::lint::help);
|
||||
}
|
||||
builder.emit();
|
||||
})
|
||||
@ -2620,6 +2595,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
||||
if let Some((msg, span)) =
|
||||
with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
|
||||
{
|
||||
// FIXME(davidtwco): make translatable
|
||||
cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| {
|
||||
let mut err = lint.build(&format!(
|
||||
"the type `{}` does not permit {}",
|
||||
@ -2996,23 +2972,19 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
|
||||
let mut found_str = DiagnosticStyledString::new();
|
||||
found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true);
|
||||
|
||||
lint.build(&format!(
|
||||
"`{}` redeclare{} with a different signature",
|
||||
this_fi.ident.name,
|
||||
if orig.get_name() == this_fi.ident.name {
|
||||
"d".to_string()
|
||||
} else {
|
||||
format!("s `{}`", orig.get_name())
|
||||
}
|
||||
))
|
||||
lint.build(if orig.get_name() == this_fi.ident.name {
|
||||
fluent::lint::builtin_clashing_extern_same_name
|
||||
} else {
|
||||
fluent::lint::builtin_clashing_extern_diff_name
|
||||
})
|
||||
.set_arg("this_fi", this_fi.ident.name)
|
||||
.set_arg("orig", orig.get_name())
|
||||
.span_label(
|
||||
get_relevant_span(orig_fi),
|
||||
&format!("`{}` previously declared here", orig.get_name()),
|
||||
)
|
||||
.span_label(
|
||||
get_relevant_span(this_fi),
|
||||
"this signature doesn't match the previous declaration",
|
||||
fluent::lint::previous_decl_label,
|
||||
)
|
||||
.span_label(get_relevant_span(this_fi), fluent::lint::mismatch_label)
|
||||
// FIXME(davidtwco): translatable expected/found
|
||||
.note_expected_found(&"", expected_str, &"", found_str)
|
||||
.emit();
|
||||
},
|
||||
@ -3096,8 +3068,8 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
|
||||
if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
|
||||
if is_null_ptr(cx, expr_deref) {
|
||||
cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
|
||||
let mut err = lint.build("dereferencing a null pointer");
|
||||
err.span_label(expr.span, "this code causes undefined behavior when executed");
|
||||
let mut err = lint.build(fluent::lint::builtin_deref_nullptr);
|
||||
err.span_label(expr.span, fluent::lint::label);
|
||||
err.emit();
|
||||
});
|
||||
}
|
||||
@ -3210,9 +3182,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
|
||||
NAMED_ASM_LABELS,
|
||||
Some(target_spans),
|
||||
|diag| {
|
||||
let mut err =
|
||||
diag.build("avoid using named labels in inline assembly");
|
||||
err.emit();
|
||||
diag.build(fluent::lint::builtin_asm_labels).emit();
|
||||
},
|
||||
BuiltinLintDiagnostics::NamedAsmLabel(
|
||||
"only local labels of the form `<number>:` should be used in inline asm"
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{context::LintContext, LateContext, LateLintPass};
|
||||
use rustc_errors::fluent;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::{fold::TypeFoldable, Ty};
|
||||
use rustc_span::{symbol::sym, Span};
|
||||
@ -51,19 +52,9 @@ fn enforce_mem_discriminant(
|
||||
if is_non_enum(ty_param) {
|
||||
cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, expr_span, |builder| {
|
||||
builder
|
||||
.build(
|
||||
"the return value of `mem::discriminant` is \
|
||||
unspecified when called with a non-enum type",
|
||||
)
|
||||
.span_note(
|
||||
args_span,
|
||||
&format!(
|
||||
"the argument to `discriminant` should be a \
|
||||
reference to an enum, but it was passed \
|
||||
a reference to a `{}`, which is not an enum.",
|
||||
ty_param,
|
||||
),
|
||||
)
|
||||
.build(fluent::lint::enum_intrinsics_mem_discriminant)
|
||||
.set_arg("ty_param", ty_param)
|
||||
.span_note(args_span, fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
@ -74,16 +65,9 @@ fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, sp
|
||||
if is_non_enum(ty_param) {
|
||||
cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, span, |builder| {
|
||||
builder
|
||||
.build(
|
||||
"the return value of `mem::variant_count` is \
|
||||
unspecified when called with a non-enum type",
|
||||
)
|
||||
.note(&format!(
|
||||
"the type parameter of `variant_count` should \
|
||||
be an enum, but it was instantiated with \
|
||||
the type `{}`, which is not an enum.",
|
||||
ty_param,
|
||||
))
|
||||
.build(fluent::lint::enum_intrinsics_mem_variant)
|
||||
.set_arg("ty_param", ty_param)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::builtin;
|
||||
use rustc_errors::fluent;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::{lint::LintExpectation, ty::TyCtxt};
|
||||
@ -43,13 +44,13 @@ fn emit_unfulfilled_expectation_lint(
|
||||
hir_id,
|
||||
expectation.emission_span,
|
||||
|diag| {
|
||||
let mut diag = diag.build("this lint expectation is unfulfilled");
|
||||
let mut diag = diag.build(fluent::lint::expectation);
|
||||
if let Some(rationale) = expectation.reason {
|
||||
diag.note(rationale.as_str());
|
||||
}
|
||||
|
||||
if expectation.is_unfulfilled_lint_expectations {
|
||||
diag.note("the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message");
|
||||
diag.note(fluent::lint::note);
|
||||
}
|
||||
|
||||
diag.emit();
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::{Applicability, SuggestionStyle};
|
||||
use rustc_errors::{fluent, Applicability, SuggestionStyle};
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
|
||||
declare_lint! {
|
||||
@ -61,41 +61,25 @@ impl HiddenUnicodeCodepoints {
|
||||
.collect();
|
||||
|
||||
cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| {
|
||||
let mut err = lint.build(&format!(
|
||||
"unicode codepoint changing visible direction of text present in {}",
|
||||
label
|
||||
));
|
||||
let (an, s) = match spans.len() {
|
||||
1 => ("an ", ""),
|
||||
_ => ("", "s"),
|
||||
};
|
||||
err.span_label(
|
||||
span,
|
||||
&format!(
|
||||
"this {} contains {}invisible unicode text flow control codepoint{}",
|
||||
label, an, s,
|
||||
),
|
||||
);
|
||||
let mut err = lint.build(fluent::lint::hidden_unicode_codepoints);
|
||||
err.set_arg("label", label);
|
||||
err.set_arg("count", spans.len());
|
||||
err.span_label(span, fluent::lint::label);
|
||||
err.note(fluent::lint::note);
|
||||
if point_at_inner_spans {
|
||||
for (c, span) in &spans {
|
||||
err.span_label(*span, format!("{:?}", c));
|
||||
}
|
||||
}
|
||||
err.note(
|
||||
"these kind of unicode codepoints change the way text flows on applications that \
|
||||
support them, but can cause confusion because they change the order of \
|
||||
characters on the screen",
|
||||
);
|
||||
if point_at_inner_spans && !spans.is_empty() {
|
||||
err.multipart_suggestion_with_style(
|
||||
"if their presence wasn't intentional, you can remove them",
|
||||
fluent::lint::suggestion_remove,
|
||||
spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
|
||||
Applicability::MachineApplicable,
|
||||
SuggestionStyle::HideCodeAlways,
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
"if you want to keep them but make them visible in your source code, you can \
|
||||
escape them",
|
||||
fluent::lint::suggestion_escape,
|
||||
spans
|
||||
.into_iter()
|
||||
.map(|(c, span)| {
|
||||
@ -109,16 +93,16 @@ impl HiddenUnicodeCodepoints {
|
||||
// FIXME: in other suggestions we've reversed the inner spans of doc comments. We
|
||||
// should do the same here to provide the same good suggestions as we do for
|
||||
// literals above.
|
||||
err.note("if their presence wasn't intentional, you can remove them");
|
||||
err.note(&format!(
|
||||
"if you want to keep them but make them visible in your source code, you can \
|
||||
escape them: {}",
|
||||
err.set_arg(
|
||||
"escaped",
|
||||
spans
|
||||
.into_iter()
|
||||
.map(|(c, _)| { format!("{:?}", c) })
|
||||
.map(|(c, _)| format!("{:?}", c))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
));
|
||||
);
|
||||
err.note(fluent::lint::suggestion_remove);
|
||||
err.note(fluent::lint::no_suggestion_note_escape);
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{fluent, Applicability};
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
|
||||
use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
|
||||
@ -36,13 +36,10 @@ impl LateLintPass<'_> for DefaultHashTypes {
|
||||
_ => return,
|
||||
};
|
||||
cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| {
|
||||
let msg = format!(
|
||||
"prefer `{}` over `{}`, it has better performance",
|
||||
replace,
|
||||
cx.tcx.item_name(def_id)
|
||||
);
|
||||
lint.build(&msg)
|
||||
.note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace))
|
||||
lint.build(fluent::lint::default_hash_types)
|
||||
.set_arg("preferred", replace)
|
||||
.set_arg("used", cx.tcx.item_name(def_id))
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
@ -99,12 +96,9 @@ impl LateLintPass<'_> for QueryStability {
|
||||
let def_id = instance.def_id();
|
||||
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
|
||||
cx.struct_span_lint(POTENTIAL_QUERY_INSTABILITY, span, |lint| {
|
||||
let msg = format!(
|
||||
"using `{}` can result in unstable query results",
|
||||
cx.tcx.item_name(def_id)
|
||||
);
|
||||
lint.build(&msg)
|
||||
.note("if you believe this case to be fine, allow this lint and add a comment explaining your rationale")
|
||||
lint.build(fluent::lint::query_instability)
|
||||
.set_arg("query", cx.tcx.item_name(def_id))
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
})
|
||||
}
|
||||
@ -146,10 +140,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
||||
segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
|
||||
);
|
||||
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
|
||||
lint.build("usage of `ty::TyKind::<kind>`")
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
.span_suggestion(
|
||||
span,
|
||||
"try using `ty::<kind>` directly",
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
@ -175,10 +169,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
lint.build("usage of `ty::TyKind::<kind>`")
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
"try using `ty::<kind>` directly",
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
@ -193,10 +187,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
lint.build("usage of `ty::TyKind::<kind>`")
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
"try using `ty::<kind>` directly",
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
@ -213,10 +207,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||
&& qpath_ty.hir_id == ty.hir_id
|
||||
{
|
||||
lint.build("usage of `ty::TyKind::<kind>`")
|
||||
lint.build(fluent::lint::tykind_kind)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
"try using `ty::<kind>` directly",
|
||||
fluent::lint::suggestion,
|
||||
"ty",
|
||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||
)
|
||||
@ -226,15 +220,16 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
lint.build("usage of `ty::TyKind`").help("try using `Ty` instead").emit();
|
||||
lint.build(fluent::lint::tykind).help(fluent::lint::help).emit();
|
||||
})
|
||||
} else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) {
|
||||
if path.segments.len() > 1 {
|
||||
cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
|
||||
lint.build(&format!("usage of qualified `ty::{}`", t))
|
||||
lint.build(fluent::lint::ty_qualified)
|
||||
.set_arg("ty", t.clone())
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
"try importing it and using it unqualified",
|
||||
fluent::lint::suggestion,
|
||||
t,
|
||||
// The import probably needs to be changed
|
||||
Applicability::MaybeIncorrect,
|
||||
@ -330,8 +325,8 @@ impl EarlyLintPass for LintPassImpl {
|
||||
LINT_PASS_IMPL_WITHOUT_MACRO,
|
||||
lint_pass.path.span,
|
||||
|lint| {
|
||||
lint.build("implementing `LintPass` by hand")
|
||||
.help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
|
||||
lint.build(fluent::lint::lintpass_by_hand)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
},
|
||||
)
|
||||
@ -371,13 +366,10 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
|
||||
return;
|
||||
}
|
||||
cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| {
|
||||
lint.build(&format!(
|
||||
"Found non-existing keyword `{}` used in \
|
||||
`#[doc(keyword = \"...\")]`",
|
||||
v,
|
||||
))
|
||||
.help("only existing keywords are allowed in core/std")
|
||||
.emit();
|
||||
lint.build(fluent::lint::non_existant_doc_keyword)
|
||||
.set_arg("keyword", v)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -431,8 +423,7 @@ impl LateLintPass<'_> for Diagnostics {
|
||||
debug!(?found_impl);
|
||||
if !found_impl {
|
||||
cx.struct_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, |lint| {
|
||||
lint.build("diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls")
|
||||
.emit();
|
||||
lint.build(fluent::lint::diag_out_of_impl).emit();
|
||||
})
|
||||
}
|
||||
|
||||
@ -450,7 +441,7 @@ impl LateLintPass<'_> for Diagnostics {
|
||||
debug!(?found_diagnostic_message);
|
||||
if !found_diagnostic_message {
|
||||
cx.struct_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, |lint| {
|
||||
lint.build("diagnostics should be created using translatable messages").emit();
|
||||
lint.build(fluent::lint::untranslatable_diag).emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
src,
|
||||
Some(sp.into()),
|
||||
|lint| {
|
||||
let mut err = lint.build(&msg);
|
||||
let mut err = lint.build(msg);
|
||||
if let Some(new_name) = &renamed {
|
||||
err.span_suggestion(
|
||||
sp,
|
||||
@ -548,7 +548,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
let mut db = lint.build(&format!("unknown lint: `{}`", name));
|
||||
let mut db = lint.build(format!("unknown lint: `{}`", name));
|
||||
if let Some(suggestion) = suggestion {
|
||||
db.span_suggestion(
|
||||
sp,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::LateContext;
|
||||
use crate::LateLintPass;
|
||||
use crate::LintContext;
|
||||
use rustc_errors::fluent;
|
||||
use rustc_hir::{Expr, ExprKind, PathSegment};
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::{symbol::sym, ExpnKind, Span};
|
||||
@ -88,16 +89,12 @@ fn lint_cstring_as_ptr(
|
||||
if let ty::Adt(adt, _) = substs.type_at(0).kind() {
|
||||
if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
|
||||
cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| {
|
||||
let mut diag = diag
|
||||
.build("getting the inner pointer of a temporary `CString`");
|
||||
diag.span_label(as_ptr_span, "this pointer will be invalid");
|
||||
diag.span_label(
|
||||
unwrap.span,
|
||||
"this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime",
|
||||
);
|
||||
diag.note("pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned");
|
||||
diag.help("for more information, see https://doc.rust-lang.org/reference/destructors.html");
|
||||
diag.emit();
|
||||
diag.build(fluent::lint::cstring_ptr)
|
||||
.span_label(as_ptr_span, fluent::lint::as_ptr_label)
|
||||
.span_label(unwrap.span, fluent::lint::unwrap_label)
|
||||
.note(fluent::lint::note)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::fluent;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
declare_lint! {
|
||||
@ -180,13 +181,13 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||
}
|
||||
has_non_ascii_idents = true;
|
||||
cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
|
||||
lint.build("identifier contains non-ASCII characters").emit();
|
||||
lint.build(fluent::lint::identifier_non_ascii_char).emit();
|
||||
});
|
||||
if check_uncommon_codepoints
|
||||
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
|
||||
{
|
||||
cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
|
||||
lint.build("identifier contains uncommon Unicode codepoints").emit();
|
||||
lint.build(fluent::lint::identifier_uncommon_codepoints).emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -216,15 +217,11 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||
.and_modify(|(existing_symbol, existing_span, existing_is_ascii)| {
|
||||
if !*existing_is_ascii || !is_ascii {
|
||||
cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| {
|
||||
lint.build(&format!(
|
||||
"identifier pair considered confusable between `{}` and `{}`",
|
||||
existing_symbol, symbol
|
||||
))
|
||||
.span_label(
|
||||
*existing_span,
|
||||
"this is where the previous identifier occurred",
|
||||
)
|
||||
.emit();
|
||||
lint.build(fluent::lint::confusable_identifier_pair)
|
||||
.set_arg("existing_sym", *existing_symbol)
|
||||
.set_arg("sym", symbol)
|
||||
.span_label(*existing_span, fluent::lint::label)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
if *existing_is_ascii && !is_ascii {
|
||||
@ -326,18 +323,20 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||
|
||||
for ((sp, ch_list), script_set) in lint_reports {
|
||||
cx.struct_span_lint(MIXED_SCRIPT_CONFUSABLES, sp, |lint| {
|
||||
let message = format!(
|
||||
"the usage of Script Group `{}` in this crate consists solely of mixed script confusables",
|
||||
script_set);
|
||||
let mut note = "the usage includes ".to_string();
|
||||
let mut includes = String::new();
|
||||
for (idx, ch) in ch_list.into_iter().enumerate() {
|
||||
if idx != 0 {
|
||||
note += ", ";
|
||||
includes += ", ";
|
||||
}
|
||||
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
|
||||
note += &char_info;
|
||||
includes += &char_info;
|
||||
}
|
||||
lint.build(&message).note(¬e).note("please recheck to make sure their usages are indeed what you want").emit();
|
||||
lint.build(fluent::lint::mixed_script_confusables)
|
||||
.set_arg("set", script_set.to_string())
|
||||
.set_arg("includes", includes)
|
||||
.note(fluent::lint::includes_note)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::{pluralize, Applicability};
|
||||
use rustc_errors::{fluent, Applicability};
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
@ -120,9 +120,10 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||
}
|
||||
|
||||
cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| {
|
||||
let mut l = lint.build("panic message is not a string literal");
|
||||
l.note(&format!("this usage of {}!() is deprecated; it will be a hard error in Rust 2021", symbol));
|
||||
l.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>");
|
||||
let mut l = lint.build(fluent::lint::non_fmt_panic);
|
||||
l.set_arg("name", symbol);
|
||||
l.note(fluent::lint::note);
|
||||
l.note(fluent::lint::more_info_note);
|
||||
if !is_arg_inside_call(arg_span, span) {
|
||||
// No clue where this argument is coming from.
|
||||
l.emit();
|
||||
@ -130,10 +131,10 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||
}
|
||||
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
|
||||
// A case of `panic!(format!(..))`.
|
||||
l.note(format!("the {}!() macro supports formatting, so there's no need for the format!() macro here", symbol).as_str());
|
||||
l.note(fluent::lint::supports_fmt_note);
|
||||
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
|
||||
l.multipart_suggestion(
|
||||
"remove the `format!(..)` macro call",
|
||||
fluent::lint::supports_fmt_suggestion,
|
||||
vec![
|
||||
(arg_span.until(open.shrink_to_hi()), "".into()),
|
||||
(close.until(arg_span.shrink_to_hi()), "".into()),
|
||||
@ -153,12 +154,18 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||
);
|
||||
|
||||
let (suggest_display, suggest_debug) = cx.tcx.infer_ctxt().enter(|infcx| {
|
||||
let display = is_str || cx.tcx.get_diagnostic_item(sym::Display).map(|t| {
|
||||
infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply()
|
||||
}) == Some(true);
|
||||
let debug = !display && cx.tcx.get_diagnostic_item(sym::Debug).map(|t| {
|
||||
infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply()
|
||||
}) == Some(true);
|
||||
let display = is_str
|
||||
|| cx.tcx.get_diagnostic_item(sym::Display).map(|t| {
|
||||
infcx
|
||||
.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env)
|
||||
.may_apply()
|
||||
}) == Some(true);
|
||||
let debug = !display
|
||||
&& cx.tcx.get_diagnostic_item(sym::Debug).map(|t| {
|
||||
infcx
|
||||
.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env)
|
||||
.may_apply()
|
||||
}) == Some(true);
|
||||
(display, debug)
|
||||
});
|
||||
|
||||
@ -175,17 +182,15 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||
if suggest_display {
|
||||
l.span_suggestion_verbose(
|
||||
arg_span.shrink_to_lo(),
|
||||
"add a \"{}\" format string to Display the message",
|
||||
fluent::lint::display_suggestion,
|
||||
"\"{}\", ",
|
||||
fmt_applicability,
|
||||
);
|
||||
} else if suggest_debug {
|
||||
l.set_arg("ty", ty);
|
||||
l.span_suggestion_verbose(
|
||||
arg_span.shrink_to_lo(),
|
||||
&format!(
|
||||
"add a \"{{:?}}\" format string to use the Debug implementation of `{}`",
|
||||
ty,
|
||||
),
|
||||
fluent::lint::debug_suggestion,
|
||||
"\"{:?}\", ",
|
||||
fmt_applicability,
|
||||
);
|
||||
@ -193,15 +198,9 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||
|
||||
if suggest_panic_any {
|
||||
if let Some((open, close, del)) = find_delimiters(cx, span) {
|
||||
l.set_arg("already_suggested", suggest_display || suggest_debug);
|
||||
l.multipart_suggestion(
|
||||
&format!(
|
||||
"{}use std::panic::panic_any instead",
|
||||
if suggest_display || suggest_debug {
|
||||
"or "
|
||||
} else {
|
||||
""
|
||||
},
|
||||
),
|
||||
fluent::lint::panic_suggestion,
|
||||
if del == '(' {
|
||||
vec![(span.until(open), "std::panic::panic_any".into())]
|
||||
} else {
|
||||
@ -260,21 +259,19 @@ fn check_panic_str<'tcx>(
|
||||
.collect(),
|
||||
};
|
||||
cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| {
|
||||
let mut l = lint.build(match n_arguments {
|
||||
1 => "panic message contains an unused formatting placeholder",
|
||||
_ => "panic message contains unused formatting placeholders",
|
||||
});
|
||||
l.note("this message is not used as a format string when given without arguments, but will be in Rust 2021");
|
||||
let mut l = lint.build(fluent::lint::non_fmt_panic_unused);
|
||||
l.set_arg("count", n_arguments);
|
||||
l.note(fluent::lint::note);
|
||||
if is_arg_inside_call(arg.span, span) {
|
||||
l.span_suggestion(
|
||||
arg.span.shrink_to_hi(),
|
||||
&format!("add the missing argument{}", pluralize!(n_arguments)),
|
||||
fluent::lint::add_args_suggestion,
|
||||
", ...",
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
l.span_suggestion(
|
||||
arg.span.shrink_to_lo(),
|
||||
"or add a \"{}\" format string to use the message literally",
|
||||
fluent::lint::add_fmt_suggestion,
|
||||
"\"{}\", ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
@ -289,17 +286,15 @@ fn check_panic_str<'tcx>(
|
||||
.map(|(i, _)| fmt_span.from_inner(InnerSpan { start: i, end: i + 1 }))
|
||||
.collect()
|
||||
});
|
||||
let msg = match &brace_spans {
|
||||
Some(v) if v.len() == 1 => "panic message contains a brace",
|
||||
_ => "panic message contains braces",
|
||||
};
|
||||
let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2);
|
||||
cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
|
||||
let mut l = lint.build(msg);
|
||||
l.note("this message is not used as a format string, but will be in Rust 2021");
|
||||
let mut l = lint.build(fluent::lint::non_fmt_panic_braces);
|
||||
l.set_arg("count", count);
|
||||
l.note(fluent::lint::note);
|
||||
if is_arg_inside_call(arg.span, span) {
|
||||
l.span_suggestion(
|
||||
arg.span.shrink_to_lo(),
|
||||
"add a \"{}\" format string to use the message literally",
|
||||
fluent::lint::suggestion,
|
||||
"\"{}\", ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
use rustc_attr as attr;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{fluent, Applicability};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
@ -137,22 +137,23 @@ impl NonCamelCaseTypes {
|
||||
|
||||
if !is_camel_case(name) {
|
||||
cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| {
|
||||
let msg = format!("{} `{}` should have an upper camel case name", sort, name);
|
||||
let mut err = lint.build(&msg);
|
||||
let mut err = lint.build(fluent::lint::non_camel_case_type);
|
||||
let cc = to_camel_case(name);
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Lowercase Letter".
|
||||
if *name != cc {
|
||||
err.span_suggestion(
|
||||
ident.span,
|
||||
"convert the identifier to upper camel case",
|
||||
fluent::lint::suggestion,
|
||||
to_camel_case(name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_label(ident.span, "should have an UpperCamelCase name");
|
||||
err.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
|
||||
err.set_arg("sort", sort);
|
||||
err.set_arg("name", name);
|
||||
err.emit();
|
||||
})
|
||||
}
|
||||
@ -281,11 +282,10 @@ impl NonSnakeCase {
|
||||
if !is_snake_case(name) {
|
||||
cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| {
|
||||
let sc = NonSnakeCase::to_snake_case(name);
|
||||
let msg = format!("{} `{}` should have a snake case name", sort, name);
|
||||
let mut err = lint.build(&msg);
|
||||
let mut err = lint.build(fluent::lint::non_snake_case);
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Uppercase Letter".
|
||||
if *name != sc {
|
||||
if name != sc {
|
||||
// We have a valid span in almost all cases, but we don't have one when linting a crate
|
||||
// name provided via the command line.
|
||||
if !ident.span.is_dummy() {
|
||||
@ -295,13 +295,13 @@ impl NonSnakeCase {
|
||||
// Instead, recommend renaming the identifier entirely or, if permitted,
|
||||
// escaping it to create a raw identifier.
|
||||
if sc_ident.name.can_be_raw() {
|
||||
("rename the identifier or convert it to a snake case raw identifier", sc_ident.to_string())
|
||||
(fluent::lint::rename_or_convert_suggestion, sc_ident.to_string())
|
||||
} else {
|
||||
err.note(&format!("`{}` cannot be used as a raw identifier", sc));
|
||||
("rename the identifier", String::new())
|
||||
err.note(fluent::lint::cannot_convert_note);
|
||||
(fluent::lint::rename_suggestion, String::new())
|
||||
}
|
||||
} else {
|
||||
("convert the identifier to snake case", sc)
|
||||
(fluent::lint::convert_suggestion, sc.clone())
|
||||
};
|
||||
|
||||
err.span_suggestion(
|
||||
@ -311,12 +311,15 @@ impl NonSnakeCase {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.help(&format!("convert the identifier to snake case: `{}`", sc));
|
||||
err.help(fluent::lint::help);
|
||||
}
|
||||
} else {
|
||||
err.span_label(ident.span, "should have a snake_case name");
|
||||
err.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
|
||||
err.set_arg("sort", sort);
|
||||
err.set_arg("name", name);
|
||||
err.set_arg("sc", sc);
|
||||
err.emit();
|
||||
});
|
||||
}
|
||||
@ -488,21 +491,22 @@ impl NonUpperCaseGlobals {
|
||||
if name.chars().any(|c| c.is_lowercase()) {
|
||||
cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| {
|
||||
let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
|
||||
let mut err =
|
||||
lint.build(&format!("{} `{}` should have an upper case name", sort, name));
|
||||
let mut err = lint.build(fluent::lint::non_upper_case_global);
|
||||
// We cannot provide meaningful suggestions
|
||||
// if the characters are in the category of "Lowercase Letter".
|
||||
if *name != uc {
|
||||
err.span_suggestion(
|
||||
ident.span,
|
||||
"convert the identifier to upper case",
|
||||
fluent::lint::suggestion,
|
||||
uc,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_label(ident.span, "should have an UPPER_CASE name");
|
||||
err.span_label(ident.span, fluent::lint::label);
|
||||
}
|
||||
|
||||
err.set_arg("sort", sort);
|
||||
err.set_arg("name", name);
|
||||
err.emit();
|
||||
})
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use crate::context::LintContext;
|
||||
use crate::rustc_middle::ty::TypeFoldable;
|
||||
use crate::LateContext;
|
||||
use crate::LateLintPass;
|
||||
use rustc_errors::fluent;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_middle::ty;
|
||||
@ -80,7 +81,6 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
let method = &call.ident.name;
|
||||
let receiver = &elements[0];
|
||||
let receiver_ty = cx.typeck_results().expr_ty(receiver);
|
||||
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
|
||||
@ -90,19 +90,14 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
||||
return;
|
||||
}
|
||||
let expr_span = expr.span;
|
||||
let note = format!(
|
||||
"the type `{:?}` which `{}` is being called on is the same as \
|
||||
the type returned from `{}`, so the method call does not do \
|
||||
anything and can be removed",
|
||||
receiver_ty, method, method,
|
||||
);
|
||||
|
||||
let span = expr_span.with_lo(receiver.span.hi());
|
||||
cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
|
||||
let method = &call.ident.name;
|
||||
let message =
|
||||
format!("call to `.{}()` on a reference in this situation does nothing", &method,);
|
||||
lint.build(&message).span_label(span, "unnecessary method call").note(¬e).emit();
|
||||
lint.build(fluent::lint::noop_method_call)
|
||||
.set_arg("method", call.ident.name)
|
||||
.set_arg("receiver_ty", receiver_ty)
|
||||
.span_label(span, fluent::lint::label)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{fluent, Applicability};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{GenericArg, PathSegment, QPath, TyKind};
|
||||
@ -30,10 +30,11 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
|
||||
}
|
||||
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
|
||||
cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
|
||||
lint.build(&format!("passing `{}` by reference", t))
|
||||
lint.build(fluent::lint::pass_by_value)
|
||||
.set_arg("ty", t.clone())
|
||||
.span_suggestion(
|
||||
ty.span,
|
||||
"try passing by value",
|
||||
fluent::lint::suggestion,
|
||||
t,
|
||||
// Changing type of function argument
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_ast::{Block, StmtKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{fluent, Applicability};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_lint! {
|
||||
@ -49,12 +49,10 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo
|
||||
}
|
||||
|
||||
cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| {
|
||||
let (msg, rem) = if multiple {
|
||||
("unnecessary trailing semicolons", "remove these semicolons")
|
||||
} else {
|
||||
("unnecessary trailing semicolon", "remove this semicolon")
|
||||
};
|
||||
lint.build(msg).span_suggestion(span, rem, "", Applicability::MaybeIncorrect).emit();
|
||||
lint.build(fluent::lint::redundant_semicolons)
|
||||
.set_arg("multiple", multiple)
|
||||
.span_suggestion(span, fluent::lint::suggestion, "", Applicability::MaybeIncorrect)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::LateContext;
|
||||
use crate::LateLintPass;
|
||||
use crate::LintContext;
|
||||
use rustc_errors::fluent;
|
||||
use rustc_hir as hir;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
@ -103,13 +104,10 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
||||
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
||||
return
|
||||
};
|
||||
let msg = format!(
|
||||
"bounds on `{}` are most likely incorrect, consider instead \
|
||||
using `{}` to detect whether a type can be trivially dropped",
|
||||
predicate,
|
||||
cx.tcx.def_path_str(needs_drop)
|
||||
);
|
||||
lint.build(&msg).emit();
|
||||
lint.build(fluent::lint::drop_trait_constraints)
|
||||
.set_arg("predicate", predicate)
|
||||
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -126,12 +124,9 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
||||
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
||||
return
|
||||
};
|
||||
let msg = format!(
|
||||
"types that do not implement `Drop` can still have drop glue, consider \
|
||||
instead using `{}` to detect whether a type is trivially dropped",
|
||||
cx.tcx.def_path_str(needs_drop)
|
||||
);
|
||||
lint.build(&msg).emit();
|
||||
lint.build(fluent::lint::drop_glue)
|
||||
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{fluent, Applicability, DiagnosticMessage};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
|
||||
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
|
||||
@ -139,7 +139,8 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
||||
// overflowing and only by 1.
|
||||
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, parent_expr.span, |lint| {
|
||||
let mut err = lint.build(&format!("range endpoint is out of range for `{}`", ty));
|
||||
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
|
||||
err.set_arg("ty", ty);
|
||||
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
|
||||
use ast::{LitIntType, LitKind};
|
||||
// We need to preserve the literal's suffix,
|
||||
@ -153,7 +154,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
||||
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
|
||||
err.span_suggestion(
|
||||
parent_expr.span,
|
||||
"use an inclusive range instead",
|
||||
fluent::lint::suggestion,
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
@ -229,38 +230,35 @@ fn report_bin_hex_error(
|
||||
(t.name_str(), actually.to_string())
|
||||
}
|
||||
};
|
||||
let mut err = lint.build(&format!("literal out of range for `{}`", t));
|
||||
let mut err = lint.build(fluent::lint::overflowing_bin_hex);
|
||||
if negative {
|
||||
// If the value is negative,
|
||||
// emits a note about the value itself, apart from the literal.
|
||||
err.note(&format!(
|
||||
"the literal `{}` (decimal `{}`) does not fit into \
|
||||
the type `{}`",
|
||||
repr_str, val, t
|
||||
));
|
||||
err.note(&format!("and the value `-{}` will become `{}{}`", repr_str, actually, t));
|
||||
err.note(fluent::lint::negative_note);
|
||||
err.note(fluent::lint::negative_becomes_note);
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"the literal `{}` (decimal `{}`) does not fit into \
|
||||
the type `{}` and will become `{}{}`",
|
||||
repr_str, val, t, actually, t
|
||||
));
|
||||
err.note(fluent::lint::positive_note);
|
||||
}
|
||||
if let Some(sugg_ty) =
|
||||
get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
|
||||
{
|
||||
err.set_arg("suggestion_ty", sugg_ty);
|
||||
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
||||
let (sans_suffix, _) = repr_str.split_at(pos);
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
&format!("consider using the type `{}` instead", sugg_ty),
|
||||
fluent::lint::suggestion,
|
||||
format!("{}{}", sans_suffix, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.help(&format!("consider using the type `{}` instead", sugg_ty));
|
||||
err.help(fluent::lint::help);
|
||||
}
|
||||
}
|
||||
err.set_arg("ty", t);
|
||||
err.set_arg("lit", repr_str);
|
||||
err.set_arg("dec", val);
|
||||
err.set_arg("actually", actually);
|
||||
err.emit();
|
||||
});
|
||||
}
|
||||
@ -353,21 +351,23 @@ fn lint_int_literal<'tcx>(
|
||||
}
|
||||
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
||||
let mut err = lint.build(&format!("literal out of range for `{}`", t.name_str()));
|
||||
err.note(&format!(
|
||||
"the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
|
||||
let mut err = lint.build(fluent::lint::overflowing_int);
|
||||
err.set_arg("ty", t.name_str());
|
||||
err.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.expect("must get snippet from literal"),
|
||||
t.name_str(),
|
||||
min,
|
||||
max,
|
||||
));
|
||||
);
|
||||
err.set_arg("min", min);
|
||||
err.set_arg("max", max);
|
||||
err.note(fluent::lint::note);
|
||||
if let Some(sugg_ty) =
|
||||
get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
|
||||
{
|
||||
err.help(&format!("consider using the type `{}` instead", sugg_ty));
|
||||
err.set_arg("suggestion_ty", sugg_ty);
|
||||
err.help(fluent::lint::help);
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
@ -395,10 +395,10 @@ fn lint_uint_literal<'tcx>(
|
||||
hir::ExprKind::Cast(..) => {
|
||||
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, par_e.span, |lint| {
|
||||
lint.build("only `u8` can be cast into `char`")
|
||||
lint.build(fluent::lint::only_cast_u8_to_char)
|
||||
.span_suggestion(
|
||||
par_e.span,
|
||||
"use a `char` literal instead",
|
||||
fluent::lint::suggestion,
|
||||
format!("'\\u{{{:X}}}'", lit_val),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
@ -429,17 +429,18 @@ fn lint_uint_literal<'tcx>(
|
||||
return;
|
||||
}
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
||||
lint.build(&format!("literal out of range for `{}`", t.name_str()))
|
||||
.note(&format!(
|
||||
"the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
|
||||
lint.build(fluent::lint::overflowing_uint)
|
||||
.set_arg("ty", t.name_str())
|
||||
.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.expect("must get snippet from literal"),
|
||||
t.name_str(),
|
||||
min,
|
||||
max,
|
||||
))
|
||||
)
|
||||
.set_arg("min", min)
|
||||
.set_arg("max", max)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
@ -471,16 +472,16 @@ fn lint_literal<'tcx>(
|
||||
};
|
||||
if is_infinite == Ok(true) {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
||||
lint.build(&format!("literal out of range for `{}`", t.name_str()))
|
||||
.note(&format!(
|
||||
"the literal `{}` does not fit into the type `{}` and will be converted to `{}::INFINITY`",
|
||||
lint.build(fluent::lint::overflowing_literal)
|
||||
.set_arg("ty", t.name_str())
|
||||
.set_arg(
|
||||
"lit",
|
||||
cx.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.expect("must get snippet from literal"),
|
||||
t.name_str(),
|
||||
t.name_str(),
|
||||
))
|
||||
)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
@ -501,7 +502,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
||||
hir::ExprKind::Binary(binop, ref l, ref r) => {
|
||||
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
|
||||
cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
|
||||
lint.build("comparison is useless due to type limits").emit();
|
||||
lint.build(fluent::lint::unused_comparisons).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -663,7 +664,7 @@ struct ImproperCTypesVisitor<'a, 'tcx> {
|
||||
enum FfiResult<'tcx> {
|
||||
FfiSafe,
|
||||
FfiPhantom(Ty<'tcx>),
|
||||
FfiUnsafe { ty: Ty<'tcx>, reason: String, help: Option<String> },
|
||||
FfiUnsafe { ty: Ty<'tcx>, reason: DiagnosticMessage, help: Option<DiagnosticMessage> },
|
||||
}
|
||||
|
||||
pub(crate) fn nonnull_optimization_guaranteed<'tcx>(
|
||||
@ -823,8 +824,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
self.emit_ffi_unsafe_type_lint(
|
||||
ty,
|
||||
sp,
|
||||
"passing raw arrays by value is not FFI-safe",
|
||||
Some("consider passing a pointer to the array"),
|
||||
fluent::lint::improper_ctypes_array_reason,
|
||||
Some(fluent::lint::improper_ctypes_array_help),
|
||||
);
|
||||
true
|
||||
} else {
|
||||
@ -867,11 +868,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
} else {
|
||||
// All fields are ZSTs; this means that the type should behave
|
||||
// like (), which is FFI-unsafe
|
||||
FfiUnsafe {
|
||||
ty,
|
||||
reason: "this struct contains only zero-sized fields".into(),
|
||||
help: None,
|
||||
}
|
||||
FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_struct_zst, help: None }
|
||||
}
|
||||
} else {
|
||||
// We can't completely trust repr(C) markings; make sure the fields are
|
||||
@ -885,7 +882,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
FfiPhantom(..) if def.is_enum() => {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "this enum contains a PhantomData field".into(),
|
||||
reason: fluent::lint::improper_ctypes_enum_phantomdata,
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
@ -921,7 +918,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
} else {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "box cannot be represented as a single pointer".to_string(),
|
||||
reason: fluent::lint::improper_ctypes_box,
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
@ -931,17 +928,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
match def.adt_kind() {
|
||||
AdtKind::Struct | AdtKind::Union => {
|
||||
let kind = if def.is_struct() { "struct" } else { "union" };
|
||||
|
||||
if !def.repr().c() && !def.repr().transparent() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: format!("this {} has unspecified layout", kind),
|
||||
help: Some(format!(
|
||||
"consider adding a `#[repr(C)]` or \
|
||||
`#[repr(transparent)]` attribute to this {}",
|
||||
kind
|
||||
)),
|
||||
reason: if def.is_struct() {
|
||||
fluent::lint::improper_ctypes_struct_layout_reason
|
||||
} else {
|
||||
fluent::lint::improper_ctypes_union_layout_reason
|
||||
},
|
||||
help: if def.is_struct() {
|
||||
Some(fluent::lint::improper_ctypes_struct_layout_help)
|
||||
} else {
|
||||
Some(fluent::lint::improper_ctypes_union_layout_help)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -950,7 +949,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if is_non_exhaustive && !def.did().is_local() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: format!("this {} is non-exhaustive", kind),
|
||||
reason: if def.is_struct() {
|
||||
fluent::lint::improper_ctypes_struct_non_exhaustive
|
||||
} else {
|
||||
fluent::lint::improper_ctypes_union_non_exhaustive
|
||||
},
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
@ -958,8 +961,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if def.non_enum_variant().fields.is_empty() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: format!("this {} has no fields", kind),
|
||||
help: Some(format!("consider adding a member to this {}", kind)),
|
||||
reason: if def.is_struct() {
|
||||
fluent::lint::improper_ctypes_struct_fieldless_reason
|
||||
} else {
|
||||
fluent::lint::improper_ctypes_union_fieldless_reason
|
||||
},
|
||||
help: if def.is_struct() {
|
||||
Some(fluent::lint::improper_ctypes_struct_fieldless_help)
|
||||
} else {
|
||||
Some(fluent::lint::improper_ctypes_union_fieldless_help)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -979,13 +990,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if repr_nullable_ptr(self.cx, ty, self.mode).is_none() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "enum has no representation hint".into(),
|
||||
help: Some(
|
||||
"consider adding a `#[repr(C)]`, \
|
||||
`#[repr(transparent)]`, or integer `#[repr(...)]` \
|
||||
attribute to this enum"
|
||||
.into(),
|
||||
),
|
||||
reason: fluent::lint::improper_ctypes_enum_repr_reason,
|
||||
help: Some(fluent::lint::improper_ctypes_enum_repr_help),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -993,7 +999,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if def.is_variant_list_non_exhaustive() && !def.did().is_local() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "this enum is non-exhaustive".into(),
|
||||
reason: fluent::lint::improper_ctypes_non_exhaustive,
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
@ -1004,7 +1010,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if is_non_exhaustive && !variant.def_id.is_local() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "this enum has non-exhaustive variants".into(),
|
||||
reason: fluent::lint::improper_ctypes_non_exhaustive_variant,
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
@ -1022,39 +1028,37 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
|
||||
ty::Char => FfiUnsafe {
|
||||
ty,
|
||||
reason: "the `char` type has no C equivalent".into(),
|
||||
help: Some("consider using `u32` or `libc::wchar_t` instead".into()),
|
||||
reason: fluent::lint::improper_ctypes_char_reason,
|
||||
help: Some(fluent::lint::improper_ctypes_char_help),
|
||||
},
|
||||
|
||||
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => FfiUnsafe {
|
||||
ty,
|
||||
reason: "128-bit integers don't currently have a known stable ABI".into(),
|
||||
help: None,
|
||||
},
|
||||
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
|
||||
FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_128bit, help: None }
|
||||
}
|
||||
|
||||
// Primitive types with a stable representation.
|
||||
ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe,
|
||||
|
||||
ty::Slice(_) => FfiUnsafe {
|
||||
ty,
|
||||
reason: "slices have no C equivalent".into(),
|
||||
help: Some("consider using a raw pointer instead".into()),
|
||||
reason: fluent::lint::improper_ctypes_slice_reason,
|
||||
help: Some(fluent::lint::improper_ctypes_slice_help),
|
||||
},
|
||||
|
||||
ty::Dynamic(..) => {
|
||||
FfiUnsafe { ty, reason: "trait objects have no C equivalent".into(), help: None }
|
||||
FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_dyn, help: None }
|
||||
}
|
||||
|
||||
ty::Str => FfiUnsafe {
|
||||
ty,
|
||||
reason: "string slices have no C equivalent".into(),
|
||||
help: Some("consider using `*const u8` and a length instead".into()),
|
||||
reason: fluent::lint::improper_ctypes_str_reason,
|
||||
help: Some(fluent::lint::improper_ctypes_str_help),
|
||||
},
|
||||
|
||||
ty::Tuple(..) => FfiUnsafe {
|
||||
ty,
|
||||
reason: "tuples have unspecified layout".into(),
|
||||
help: Some("consider using a struct instead".into()),
|
||||
reason: fluent::lint::improper_ctypes_tuple_reason,
|
||||
help: Some(fluent::lint::improper_ctypes_tuple_help),
|
||||
},
|
||||
|
||||
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
|
||||
@ -1085,12 +1089,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if self.is_internal_abi(sig.abi()) {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "this function pointer has Rust-specific calling convention".into(),
|
||||
help: Some(
|
||||
"consider using an `extern fn(...) -> ...` \
|
||||
function pointer instead"
|
||||
.into(),
|
||||
),
|
||||
reason: fluent::lint::improper_ctypes_fnptr_reason,
|
||||
help: Some(fluent::lint::improper_ctypes_fnptr_help),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1121,7 +1121,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
// While opaque types are checked for earlier, if a projection in a struct field
|
||||
// normalizes to an opaque type, then it will reach this branch.
|
||||
ty::Opaque(..) => {
|
||||
FfiUnsafe { ty, reason: "opaque types have no C equivalent".into(), help: None }
|
||||
FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_opaque, help: None }
|
||||
}
|
||||
|
||||
// `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
|
||||
@ -1147,8 +1147,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
note: &str,
|
||||
help: Option<&str>,
|
||||
note: DiagnosticMessage,
|
||||
help: Option<DiagnosticMessage>,
|
||||
) {
|
||||
let lint = match self.mode {
|
||||
CItemKind::Declaration => IMPROPER_CTYPES,
|
||||
@ -1160,18 +1160,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
CItemKind::Declaration => "block",
|
||||
CItemKind::Definition => "fn",
|
||||
};
|
||||
let mut diag = lint.build(&format!(
|
||||
"`extern` {} uses type `{}`, which is not FFI-safe",
|
||||
item_description, ty
|
||||
));
|
||||
diag.span_label(sp, "not FFI-safe");
|
||||
let mut diag = lint.build(fluent::lint::improper_ctypes);
|
||||
diag.set_arg("ty", ty);
|
||||
diag.set_arg("desc", item_description);
|
||||
diag.span_label(sp, fluent::lint::label);
|
||||
if let Some(help) = help {
|
||||
diag.help(help);
|
||||
}
|
||||
diag.note(note);
|
||||
if let ty::Adt(def, _) = ty.kind() {
|
||||
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) {
|
||||
diag.span_note(sp, "the type is defined here");
|
||||
diag.span_note(sp, fluent::lint::note);
|
||||
}
|
||||
}
|
||||
diag.emit();
|
||||
@ -1208,7 +1207,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() {
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None);
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint::improper_ctypes_opaque, None);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -1250,13 +1249,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
|
||||
FfiResult::FfiSafe => {}
|
||||
FfiResult::FfiPhantom(ty) => {
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
|
||||
self.emit_ffi_unsafe_type_lint(
|
||||
ty,
|
||||
sp,
|
||||
fluent::lint::improper_ctypes_only_phantomdata,
|
||||
None,
|
||||
);
|
||||
}
|
||||
// If `ty` is a `repr(transparent)` newtype, and the non-zero-sized type is a generic
|
||||
// argument, which after substitution, is `()`, then this branch can be hit.
|
||||
FfiResult::FfiUnsafe { ty, .. } if is_return_type && ty.is_unit() => {}
|
||||
FfiResult::FfiUnsafe { ty, reason, help } => {
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, &reason, help.as_deref());
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1383,12 +1387,9 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
|
||||
VARIANT_SIZE_DIFFERENCES,
|
||||
enum_definition.variants[largest_index].span,
|
||||
|lint| {
|
||||
lint.build(&format!(
|
||||
"enum variant is more than three times \
|
||||
larger ({} bytes) than the next largest",
|
||||
largest
|
||||
))
|
||||
.emit();
|
||||
lint.build(fluent::lint::variant_size_differences)
|
||||
.set_arg("largest", largest)
|
||||
.emit();
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -1511,13 +1512,13 @@ impl InvalidAtomicOrdering {
|
||||
{
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| {
|
||||
if method == sym::load {
|
||||
diag.build("atomic loads cannot have `Release` or `AcqRel` ordering")
|
||||
.help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")
|
||||
diag.build(fluent::lint::atomic_ordering_load)
|
||||
.help(fluent::lint::help)
|
||||
.emit()
|
||||
} else {
|
||||
debug_assert_eq!(method, sym::store);
|
||||
diag.build("atomic stores cannot have `Acquire` or `AcqRel` ordering")
|
||||
.help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")
|
||||
diag.build(fluent::lint::atomic_ordering_store)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
}
|
||||
});
|
||||
@ -1532,8 +1533,8 @@ impl InvalidAtomicOrdering {
|
||||
&& Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
|
||||
{
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| {
|
||||
diag.build("memory fences cannot have `Relaxed` ordering")
|
||||
.help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")
|
||||
diag.build(fluent::lint::atomic_ordering_fence)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
@ -1553,13 +1554,11 @@ impl InvalidAtomicOrdering {
|
||||
|
||||
if matches!(fail_ordering, sym::Release | sym::AcqRel) {
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg.span, |diag| {
|
||||
diag.build(&format!(
|
||||
"`{method}`'s failure ordering may not be `Release` or `AcqRel`, \
|
||||
since a failed `{method}` does not result in a write",
|
||||
))
|
||||
.span_label(fail_order_arg.span, "invalid failure ordering")
|
||||
.help("consider using `Acquire` or `Relaxed` failure ordering instead")
|
||||
.emit();
|
||||
diag.build(fluent::lint::atomic_ordering_invalid)
|
||||
.set_arg("method", method)
|
||||
.span_label(fail_order_arg.span, fluent::lint::label)
|
||||
.help(fluent::lint::help)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1577,18 +1576,20 @@ impl InvalidAtomicOrdering {
|
||||
fail_ordering
|
||||
};
|
||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, success_order_arg.span, |diag| {
|
||||
diag.build(&format!(
|
||||
"`{method}`'s success ordering must be at least as strong as its failure ordering"
|
||||
))
|
||||
.span_label(fail_order_arg.span, format!("`{fail_ordering}` failure ordering"))
|
||||
.span_label(success_order_arg.span, format!("`{success_ordering}` success ordering"))
|
||||
.span_suggestion_short(
|
||||
success_order_arg.span,
|
||||
format!("consider using `{success_suggestion}` success ordering instead"),
|
||||
format!("std::sync::atomic::Ordering::{success_suggestion}"),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
diag.build(fluent::lint::atomic_ordering_invalid_fail_success)
|
||||
.set_arg("method", method)
|
||||
.set_arg("fail_ordering", fail_ordering)
|
||||
.set_arg("success_ordering", success_ordering)
|
||||
.set_arg("success_suggestion", success_suggestion)
|
||||
.span_label(fail_order_arg.span, fluent::lint::fail_label)
|
||||
.span_label(success_order_arg.span, fluent::lint::success_label)
|
||||
.span_suggestion_short(
|
||||
success_order_arg.span,
|
||||
fluent::lint::suggestion,
|
||||
format!("std::sync::atomic::Ordering::{success_suggestion}"),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::util::{classify, parser};
|
||||
use rustc_ast::{ExprKind, StmtKind};
|
||||
use rustc_errors::{pluralize, Applicability, MultiSpan};
|
||||
use rustc_errors::{fluent, pluralize, Applicability, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
@ -155,22 +155,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
|
||||
if let Some(must_use_op) = must_use_op {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, expr.span, |lint| {
|
||||
let mut lint = lint.build(&format!("unused {} that must be used", must_use_op));
|
||||
lint.span_label(expr.span, &format!("the {} produces a value", must_use_op));
|
||||
lint.span_suggestion_verbose(
|
||||
expr.span.shrink_to_lo(),
|
||||
"use `let _ = ...` to ignore the resulting value",
|
||||
"let _ = ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
lint.emit();
|
||||
lint.build(fluent::lint::unused_op)
|
||||
.set_arg("op", must_use_op)
|
||||
.span_label(expr.span, fluent::lint::label)
|
||||
.span_suggestion_verbose(
|
||||
expr.span.shrink_to_lo(),
|
||||
fluent::lint::suggestion,
|
||||
"let _ = ",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
op_warned = true;
|
||||
}
|
||||
|
||||
if !(type_permits_lack_of_use || fn_warned || op_warned) {
|
||||
cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
|
||||
lint.build(&format!("unused result of type `{}`", ty)).emit();
|
||||
lint.build(fluent::lint::unused_result).set_arg("ty", ty).emit();
|
||||
});
|
||||
}
|
||||
|
||||
@ -267,23 +268,27 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
},
|
||||
ty::Closure(..) => {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
||||
let mut err = lint.build(&format!(
|
||||
"unused {}closure{}{} that must be used",
|
||||
descr_pre, plural_suffix, descr_post,
|
||||
));
|
||||
err.note("closures are lazy and do nothing unless called");
|
||||
err.emit();
|
||||
// FIXME(davidtwco): this isn't properly translatable becauses of the
|
||||
// pre/post strings
|
||||
lint.build(fluent::lint::unused_closure)
|
||||
.set_arg("count", plural_len)
|
||||
.set_arg("pre", descr_pre)
|
||||
.set_arg("post", descr_post)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
true
|
||||
}
|
||||
ty::Generator(..) => {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
||||
let mut err = lint.build(&format!(
|
||||
"unused {}generator{}{} that must be used",
|
||||
descr_pre, plural_suffix, descr_post,
|
||||
));
|
||||
err.note("generators are lazy and do nothing unless resumed");
|
||||
err.emit();
|
||||
// FIXME(davidtwco): this isn't properly translatable becauses of the
|
||||
// pre/post strings
|
||||
lint.build(fluent::lint::unused_generator)
|
||||
.set_arg("count", plural_len)
|
||||
.set_arg("pre", descr_pre)
|
||||
.set_arg("post", descr_post)
|
||||
.note(fluent::lint::note)
|
||||
.emit();
|
||||
});
|
||||
true
|
||||
}
|
||||
@ -305,13 +310,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
) -> bool {
|
||||
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
||||
let msg = format!(
|
||||
"unused {}`{}`{} that must be used",
|
||||
descr_pre_path,
|
||||
cx.tcx.def_path_str(def_id),
|
||||
descr_post_path
|
||||
);
|
||||
let mut err = lint.build(&msg);
|
||||
// FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
|
||||
// strings
|
||||
let mut err = lint.build(fluent::lint::unused_def);
|
||||
err.set_arg("pre", descr_pre_path);
|
||||
err.set_arg("post", descr_post_path);
|
||||
err.set_arg("def", cx.tcx.def_path_str(def_id));
|
||||
// check for #[must_use = "..."]
|
||||
if let Some(note) = attr.value_str() {
|
||||
err.note(note.as_str());
|
||||
@ -356,20 +360,20 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
|
||||
cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if ty.needs_drop(cx.tcx, cx.param_env) {
|
||||
let mut lint = lint.build("path statement drops value");
|
||||
let mut lint = lint.build(fluent::lint::path_statement_drop);
|
||||
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
|
||||
lint.span_suggestion(
|
||||
s.span,
|
||||
"use `drop` to clarify the intent",
|
||||
fluent::lint::suggestion,
|
||||
format!("drop({});", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
lint.span_help(s.span, "use `drop` to clarify the intent");
|
||||
lint.span_help(s.span, fluent::lint::suggestion);
|
||||
}
|
||||
lint.emit();
|
||||
} else {
|
||||
lint.build("path statement with no effect").emit();
|
||||
lint.build(fluent::lint::path_statement_no_effect).emit();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -540,15 +544,19 @@ trait UnusedDelimLint {
|
||||
}
|
||||
|
||||
cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
|
||||
let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg);
|
||||
let mut err = lint.build(&span_msg);
|
||||
let replacement = vec![
|
||||
(spans.0, if keep_space.0 { " ".into() } else { "".into() }),
|
||||
(spans.1, if keep_space.1 { " ".into() } else { "".into() }),
|
||||
];
|
||||
let suggestion = format!("remove these {}", Self::DELIM_STR);
|
||||
err.multipart_suggestion(&suggestion, replacement, Applicability::MachineApplicable);
|
||||
err.emit();
|
||||
lint.build(fluent::lint::unused_delim)
|
||||
.set_arg("delim", Self::DELIM_STR)
|
||||
.set_arg("item", msg)
|
||||
.multipart_suggestion(
|
||||
fluent::lint::suggestion,
|
||||
replacement,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1110,7 +1118,7 @@ impl UnusedImportBraces {
|
||||
};
|
||||
|
||||
cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
|
||||
lint.build(&format!("braces around {} is unnecessary", node_name)).emit();
|
||||
lint.build(fluent::lint::unused_import_braces).set_arg("node", node_name).emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1161,15 +1169,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
|
||||
for adj in cx.typeck_results().expr_adjustments(e) {
|
||||
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
|
||||
cx.struct_span_lint(UNUSED_ALLOCATION, e.span, |lint| {
|
||||
let msg = match m {
|
||||
adjustment::AutoBorrowMutability::Not => {
|
||||
"unnecessary allocation, use `&` instead"
|
||||
}
|
||||
lint.build(match m {
|
||||
adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation,
|
||||
adjustment::AutoBorrowMutability::Mut { .. } => {
|
||||
"unnecessary allocation, use `&mut` instead"
|
||||
fluent::lint::unused_allocation_mut
|
||||
}
|
||||
};
|
||||
lint.build(msg).emit();
|
||||
})
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ use std::cmp;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_errors::{
|
||||
Diagnostic, DiagnosticBuilder, DiagnosticId, EmissionGuarantee, ErrorGuaranteed, MultiSpan,
|
||||
Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee,
|
||||
ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
@ -231,7 +232,7 @@ pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a,
|
||||
|
||||
impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
|
||||
/// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
|
||||
pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, G> {
|
||||
pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> {
|
||||
self.0.set_primary_message(msg);
|
||||
self.0.set_is_lint();
|
||||
self.0
|
||||
|
@ -611,6 +611,12 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable)]
|
||||
pub enum PredicateKind<'tcx> {
|
||||
|
@ -550,7 +550,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||
id,
|
||||
span,
|
||||
|lint| {
|
||||
lint.build(&msg).emit();
|
||||
lint.build(msg).emit();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -1163,7 +1163,7 @@ impl CheckAttrVisitor<'_> {
|
||||
hir_id,
|
||||
meta.span(),
|
||||
|lint| {
|
||||
lint.build(&"invalid `doc` attribute").emit();
|
||||
lint.build("invalid `doc` attribute").emit();
|
||||
},
|
||||
);
|
||||
is_valid = false;
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: Found non-existing keyword `tadam` used in `#[doc(keyword = "...")]`
|
||||
error: found non-existing keyword `tadam` used in `#[doc(keyword = \"...\")]`
|
||||
--> $DIR/existing_doc_keyword.rs:10:1
|
||||
|
|
||||
LL | #[doc(keyword = "tadam")]
|
||||
|
@ -1,6 +1,8 @@
|
||||
// check-fail
|
||||
// Tests error conditions for specifying diagnostics using #[derive(SessionDiagnostic)]
|
||||
|
||||
// normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
|
||||
|
||||
// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
|
||||
// changing the output of this test. Since SessionDiagnostic is strictly internal to the compiler
|
||||
// the test is just ignored on stable and beta:
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: `#[derive(SessionDiagnostic)]` can only be used on structs
|
||||
--> $DIR/diagnostic-derive.rs:37:1
|
||||
--> $DIR/diagnostic-derive.rs:39:1
|
||||
|
|
||||
LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
LL | |
|
||||
@ -10,13 +10,13 @@ LL | | }
|
||||
| |_^
|
||||
|
||||
error: `#[error = ...]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:46:1
|
||||
--> $DIR/diagnostic-derive.rs:48:1
|
||||
|
|
||||
LL | #[error = "E0123"]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[nonsense(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:51:1
|
||||
--> $DIR/diagnostic-derive.rs:53:1
|
||||
|
|
||||
LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -24,7 +24,7 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
= help: only `error`, `warning`, `help` and `note` are valid attributes
|
||||
|
||||
error: diagnostic kind not specified
|
||||
--> $DIR/diagnostic-derive.rs:51:1
|
||||
--> $DIR/diagnostic-derive.rs:53:1
|
||||
|
|
||||
LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
LL | |
|
||||
@ -36,7 +36,7 @@ LL | | struct InvalidStructAttr {}
|
||||
= help: use the `#[error(...)]` attribute to create an error
|
||||
|
||||
error: `#[error("...")]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:58:9
|
||||
--> $DIR/diagnostic-derive.rs:60:9
|
||||
|
|
||||
LL | #[error("E0123")]
|
||||
| ^^^^^^^
|
||||
@ -44,7 +44,7 @@ LL | #[error("E0123")]
|
||||
= help: first argument of the attribute should be the diagnostic slug
|
||||
|
||||
error: diagnostic slug not specified
|
||||
--> $DIR/diagnostic-derive.rs:58:1
|
||||
--> $DIR/diagnostic-derive.rs:60:1
|
||||
|
|
||||
LL | / #[error("E0123")]
|
||||
LL | |
|
||||
@ -55,7 +55,7 @@ LL | | struct InvalidLitNestedAttr {}
|
||||
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
|
||||
|
||||
error: `#[error(nonsense(...))]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:69:9
|
||||
--> $DIR/diagnostic-derive.rs:71:9
|
||||
|
|
||||
LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -63,7 +63,7 @@ LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")]
|
||||
= help: first argument of the attribute should be the diagnostic slug
|
||||
|
||||
error: diagnostic slug not specified
|
||||
--> $DIR/diagnostic-derive.rs:69:1
|
||||
--> $DIR/diagnostic-derive.rs:71:1
|
||||
|
|
||||
LL | / #[error(nonsense("foo"), code = "E0123", slug = "foo")]
|
||||
LL | |
|
||||
@ -74,7 +74,7 @@ LL | | struct InvalidNestedStructAttr1 {}
|
||||
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
|
||||
|
||||
error: `#[error(nonsense = ...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:75:9
|
||||
--> $DIR/diagnostic-derive.rs:77:9
|
||||
|
|
||||
LL | #[error(nonsense = "...", code = "E0123", slug = "foo")]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -82,7 +82,7 @@ LL | #[error(nonsense = "...", code = "E0123", slug = "foo")]
|
||||
= help: first argument of the attribute should be the diagnostic slug
|
||||
|
||||
error: diagnostic slug not specified
|
||||
--> $DIR/diagnostic-derive.rs:75:1
|
||||
--> $DIR/diagnostic-derive.rs:77:1
|
||||
|
|
||||
LL | / #[error(nonsense = "...", code = "E0123", slug = "foo")]
|
||||
LL | |
|
||||
@ -93,7 +93,7 @@ LL | | struct InvalidNestedStructAttr2 {}
|
||||
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
|
||||
|
||||
error: `#[error(nonsense = ...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:81:9
|
||||
--> $DIR/diagnostic-derive.rs:83:9
|
||||
|
|
||||
LL | #[error(nonsense = 4, code = "E0123", slug = "foo")]
|
||||
| ^^^^^^^^^^^^
|
||||
@ -101,7 +101,7 @@ LL | #[error(nonsense = 4, code = "E0123", slug = "foo")]
|
||||
= help: first argument of the attribute should be the diagnostic slug
|
||||
|
||||
error: diagnostic slug not specified
|
||||
--> $DIR/diagnostic-derive.rs:81:1
|
||||
--> $DIR/diagnostic-derive.rs:83:1
|
||||
|
|
||||
LL | / #[error(nonsense = 4, code = "E0123", slug = "foo")]
|
||||
LL | |
|
||||
@ -112,7 +112,7 @@ LL | | struct InvalidNestedStructAttr3 {}
|
||||
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
|
||||
|
||||
error: `#[error(slug = ...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:87:59
|
||||
--> $DIR/diagnostic-derive.rs:89:59
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
|
||||
| ^^^^^^^^^^^^
|
||||
@ -120,103 +120,103 @@ LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
|
||||
= help: only `code` is a valid nested attributes following the slug
|
||||
|
||||
error: `#[suggestion = ...]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:94:5
|
||||
--> $DIR/diagnostic-derive.rs:96:5
|
||||
|
|
||||
LL | #[suggestion = "bar"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: specified multiple times
|
||||
--> $DIR/diagnostic-derive.rs:101:1
|
||||
--> $DIR/diagnostic-derive.rs:103:1
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: previously specified here
|
||||
--> $DIR/diagnostic-derive.rs:100:1
|
||||
--> $DIR/diagnostic-derive.rs:102:1
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: specified multiple times
|
||||
--> $DIR/diagnostic-derive.rs:101:1
|
||||
--> $DIR/diagnostic-derive.rs:103:1
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: previously specified here
|
||||
--> $DIR/diagnostic-derive.rs:100:1
|
||||
--> $DIR/diagnostic-derive.rs:102:1
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: specified multiple times
|
||||
--> $DIR/diagnostic-derive.rs:101:50
|
||||
--> $DIR/diagnostic-derive.rs:103:50
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: previously specified here
|
||||
--> $DIR/diagnostic-derive.rs:100:50
|
||||
--> $DIR/diagnostic-derive.rs:102:50
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^
|
||||
|
||||
error: specified multiple times
|
||||
--> $DIR/diagnostic-derive.rs:109:1
|
||||
--> $DIR/diagnostic-derive.rs:111:1
|
||||
|
|
||||
LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: previously specified here
|
||||
--> $DIR/diagnostic-derive.rs:108:1
|
||||
--> $DIR/diagnostic-derive.rs:110:1
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: specified multiple times
|
||||
--> $DIR/diagnostic-derive.rs:109:1
|
||||
--> $DIR/diagnostic-derive.rs:111:1
|
||||
|
|
||||
LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: previously specified here
|
||||
--> $DIR/diagnostic-derive.rs:108:1
|
||||
--> $DIR/diagnostic-derive.rs:110:1
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: specified multiple times
|
||||
--> $DIR/diagnostic-derive.rs:109:52
|
||||
--> $DIR/diagnostic-derive.rs:111:52
|
||||
|
|
||||
LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: previously specified here
|
||||
--> $DIR/diagnostic-derive.rs:108:50
|
||||
--> $DIR/diagnostic-derive.rs:110:50
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^
|
||||
|
||||
error: specified multiple times
|
||||
--> $DIR/diagnostic-derive.rs:116:66
|
||||
--> $DIR/diagnostic-derive.rs:118:66
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: previously specified here
|
||||
--> $DIR/diagnostic-derive.rs:116:50
|
||||
--> $DIR/diagnostic-derive.rs:118:50
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
|
||||
| ^^^^^^^
|
||||
|
||||
error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:121:43
|
||||
--> $DIR/diagnostic-derive.rs:123:43
|
||||
|
|
||||
LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: diagnostic kind not specified
|
||||
--> $DIR/diagnostic-derive.rs:126:1
|
||||
--> $DIR/diagnostic-derive.rs:128:1
|
||||
|
|
||||
LL | struct KindNotProvided {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -224,7 +224,7 @@ LL | struct KindNotProvided {}
|
||||
= help: use the `#[error(...)]` attribute to create an error
|
||||
|
||||
error: diagnostic slug not specified
|
||||
--> $DIR/diagnostic-derive.rs:129:1
|
||||
--> $DIR/diagnostic-derive.rs:131:1
|
||||
|
|
||||
LL | / #[error(code = "E0456")]
|
||||
LL | |
|
||||
@ -234,13 +234,13 @@ LL | | struct SlugNotProvided {}
|
||||
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
|
||||
|
||||
error: the `#[primary_span]` attribute can only be applied to fields of type `Span`
|
||||
--> $DIR/diagnostic-derive.rs:140:5
|
||||
--> $DIR/diagnostic-derive.rs:142:5
|
||||
|
|
||||
LL | #[primary_span]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[nonsense]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:148:5
|
||||
--> $DIR/diagnostic-derive.rs:150:5
|
||||
|
|
||||
LL | #[nonsense]
|
||||
| ^^^^^^^^^^^
|
||||
@ -248,19 +248,19 @@ LL | #[nonsense]
|
||||
= help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes
|
||||
|
||||
error: the `#[label(...)]` attribute can only be applied to fields of type `Span`
|
||||
--> $DIR/diagnostic-derive.rs:165:5
|
||||
--> $DIR/diagnostic-derive.rs:167:5
|
||||
|
|
||||
LL | #[label(typeck::label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `name` doesn't refer to a field on this type
|
||||
--> $DIR/diagnostic-derive.rs:173:45
|
||||
--> $DIR/diagnostic-derive.rs:175:45
|
||||
|
|
||||
LL | #[suggestion(typeck::suggestion, code = "{name}")]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: invalid format string: expected `'}'` but string was terminated
|
||||
--> $DIR/diagnostic-derive.rs:178:16
|
||||
--> $DIR/diagnostic-derive.rs:180:16
|
||||
|
|
||||
LL | #[derive(SessionDiagnostic)]
|
||||
| - ^ expected `'}'` in format string
|
||||
@ -271,7 +271,7 @@ LL | #[derive(SessionDiagnostic)]
|
||||
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/diagnostic-derive.rs:188:15
|
||||
--> $DIR/diagnostic-derive.rs:190:15
|
||||
|
|
||||
LL | #[derive(SessionDiagnostic)]
|
||||
| ^ unmatched `}` in format string
|
||||
@ -280,13 +280,13 @@ LL | #[derive(SessionDiagnostic)]
|
||||
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: the `#[label(...)]` attribute can only be applied to fields of type `Span`
|
||||
--> $DIR/diagnostic-derive.rs:208:5
|
||||
--> $DIR/diagnostic-derive.rs:210:5
|
||||
|
|
||||
LL | #[label(typeck::label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[suggestion(nonsense = ...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:233:18
|
||||
--> $DIR/diagnostic-derive.rs:235:18
|
||||
|
|
||||
LL | #[suggestion(nonsense = "bar")]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -294,7 +294,7 @@ LL | #[suggestion(nonsense = "bar")]
|
||||
= help: only `message`, `code` and `applicability` are valid field attributes
|
||||
|
||||
error: `#[suggestion(msg = ...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:241:18
|
||||
--> $DIR/diagnostic-derive.rs:243:18
|
||||
|
|
||||
LL | #[suggestion(msg = "bar")]
|
||||
| ^^^^^^^^^^^
|
||||
@ -302,7 +302,7 @@ LL | #[suggestion(msg = "bar")]
|
||||
= help: only `message`, `code` and `applicability` are valid field attributes
|
||||
|
||||
error: wrong field type for suggestion
|
||||
--> $DIR/diagnostic-derive.rs:263:5
|
||||
--> $DIR/diagnostic-derive.rs:265:5
|
||||
|
|
||||
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
|
||||
LL | |
|
||||
@ -312,7 +312,7 @@ LL | | suggestion: Applicability,
|
||||
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
|
||||
|
||||
error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
|
||||
--> $DIR/diagnostic-derive.rs:278:5
|
||||
--> $DIR/diagnostic-derive.rs:280:5
|
||||
|
|
||||
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
|
||||
LL | |
|
||||
@ -320,7 +320,7 @@ LL | | suggestion: (Span, Span, Applicability),
|
||||
| |___________________________________________^
|
||||
|
||||
error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
|
||||
--> $DIR/diagnostic-derive.rs:286:5
|
||||
--> $DIR/diagnostic-derive.rs:288:5
|
||||
|
|
||||
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
|
||||
LL | |
|
||||
@ -328,72 +328,66 @@ LL | | suggestion: (Applicability, Applicability, Span),
|
||||
| |____________________________________________________^
|
||||
|
||||
error: `#[label = ...]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:294:5
|
||||
--> $DIR/diagnostic-derive.rs:296:5
|
||||
|
|
||||
LL | #[label = "bar"]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: applicability cannot be set in both the field and attribute
|
||||
--> $DIR/diagnostic-derive.rs:445:52
|
||||
--> $DIR/diagnostic-derive.rs:447:52
|
||||
|
|
||||
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: invalid applicability
|
||||
--> $DIR/diagnostic-derive.rs:453:52
|
||||
--> $DIR/diagnostic-derive.rs:455:52
|
||||
|
|
||||
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[label(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:516:5
|
||||
--> $DIR/diagnostic-derive.rs:518:5
|
||||
|
|
||||
LL | #[label(typeck::label, foo)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[label(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:524:5
|
||||
--> $DIR/diagnostic-derive.rs:526:5
|
||||
|
|
||||
LL | #[label(typeck::label, foo = "...")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[label(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:532:5
|
||||
--> $DIR/diagnostic-derive.rs:534:5
|
||||
|
|
||||
LL | #[label(typeck::label, foo("..."))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: cannot find attribute `nonsense` in this scope
|
||||
--> $DIR/diagnostic-derive.rs:51:3
|
||||
--> $DIR/diagnostic-derive.rs:53:3
|
||||
|
|
||||
LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: cannot find attribute `nonsense` in this scope
|
||||
--> $DIR/diagnostic-derive.rs:148:7
|
||||
--> $DIR/diagnostic-derive.rs:150:7
|
||||
|
|
||||
LL | #[nonsense]
|
||||
| ^^^^^^^^
|
||||
|
||||
error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
|
||||
--> $DIR/diagnostic-derive.rs:64:9
|
||||
--> $DIR/diagnostic-derive.rs:66:9
|
||||
|
|
||||
LL | #[error(nonsense, code = "E0123")]
|
||||
| ^^^^^^^^ not found in `rustc_errors::fluent`
|
||||
|
||||
error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
|
||||
--> $DIR/diagnostic-derive.rs:338:10
|
||||
--> $DIR/diagnostic-derive.rs:340:10
|
||||
|
|
||||
LL | #[derive(SessionDiagnostic)]
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
|
||||
|
|
||||
= help: the following other types implement trait `IntoDiagnosticArg`:
|
||||
&'a str
|
||||
Ident
|
||||
String
|
||||
Symbol
|
||||
rustc_middle::ty::Ty<'tcx>
|
||||
usize
|
||||
= help: normalized in stderr
|
||||
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
||||
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:538:19
|
||||
|
|
||||
|
@ -5,9 +5,9 @@ LL | panic!({ "foo" });
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(non_fmt_panics)]` on by default
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!("{}", { "foo" });
|
||||
| +++++
|
||||
|
@ -73,9 +73,9 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, S);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | assert!(false, "{}", S);
|
||||
| +++++
|
||||
@ -86,9 +86,9 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, 123);
|
||||
| ^^^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | assert!(false, "{}", 123);
|
||||
| +++++
|
||||
@ -99,9 +99,9 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, Some(123));
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{:?}" format string to use the Debug implementation of `Option<i32>`
|
||||
help: add a "{:?}" format string to use the `Debug` implementation of `Option<i32>`
|
||||
|
|
||||
LL | assert!(false, "{:?}", Some(123));
|
||||
| +++++++
|
||||
@ -124,9 +124,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(C);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!("{}", C);
|
||||
| +++++
|
||||
@ -137,9 +137,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(S);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!("{}", S);
|
||||
| +++++
|
||||
@ -150,9 +150,9 @@ warning: panic message is not a string literal
|
||||
LL | unreachable!(S);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | unreachable!("{}", S);
|
||||
| +++++
|
||||
@ -163,9 +163,9 @@ warning: panic message is not a string literal
|
||||
LL | unreachable!(S);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | unreachable!("{}", S);
|
||||
| +++++
|
||||
@ -176,9 +176,9 @@ warning: panic message is not a string literal
|
||||
LL | std::panic!(123);
|
||||
| ^^^
|
||||
|
|
||||
= note: this usage of std::panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `std::panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | std::panic!("{}", 123);
|
||||
| +++++
|
||||
@ -193,9 +193,9 @@ warning: panic message is not a string literal
|
||||
LL | core::panic!(&*"abc");
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: this usage of core::panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `core::panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | core::panic!("{}", &*"abc");
|
||||
| +++++
|
||||
@ -206,9 +206,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(Some(123));
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{:?}" format string to use the Debug implementation of `Option<i32>`
|
||||
help: add a "{:?}" format string to use the `Debug` implementation of `Option<i32>`
|
||||
|
|
||||
LL | panic!("{:?}", Some(123));
|
||||
| +++++++
|
||||
@ -259,9 +259,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(a!());
|
||||
| ^^^^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!("{}", a!());
|
||||
| +++++
|
||||
@ -276,9 +276,9 @@ warning: panic message is not a string literal
|
||||
LL | unreachable!(a!());
|
||||
| ^^^^
|
||||
|
|
||||
= note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | unreachable!("{}", a!());
|
||||
| +++++
|
||||
@ -289,9 +289,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(format!("{}", 1));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
= note: the panic!() macro supports formatting, so there's no need for the format!() macro here
|
||||
= note: the `panic!()` macro supports formatting, so there's no need for the `format!()` macro here
|
||||
help: remove the `format!(..)` macro call
|
||||
|
|
||||
LL - panic!(format!("{}", 1));
|
||||
@ -304,9 +304,9 @@ warning: panic message is not a string literal
|
||||
LL | unreachable!(format!("{}", 1));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
= note: the unreachable!() macro supports formatting, so there's no need for the format!() macro here
|
||||
= note: the `unreachable!()` macro supports formatting, so there's no need for the `format!()` macro here
|
||||
help: remove the `format!(..)` macro call
|
||||
|
|
||||
LL - unreachable!(format!("{}", 1));
|
||||
@ -319,9 +319,9 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, format!("{}", 1));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
= note: the assert!() macro supports formatting, so there's no need for the format!() macro here
|
||||
= note: the `assert!()` macro supports formatting, so there's no need for the `format!()` macro here
|
||||
help: remove the `format!(..)` macro call
|
||||
|
|
||||
LL - assert!(false, format!("{}", 1));
|
||||
@ -334,9 +334,9 @@ warning: panic message is not a string literal
|
||||
LL | debug_assert!(false, format!("{}", 1));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this usage of debug_assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `debug_assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
= note: the debug_assert!() macro supports formatting, so there's no need for the format!() macro here
|
||||
= note: the `debug_assert!()` macro supports formatting, so there's no need for the `format!()` macro here
|
||||
help: remove the `format!(..)` macro call
|
||||
|
|
||||
LL - debug_assert!(false, format!("{}", 1));
|
||||
@ -349,9 +349,9 @@ warning: panic message is not a string literal
|
||||
LL | panic![123];
|
||||
| ^^^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!["{}", 123];
|
||||
| +++++
|
||||
@ -366,9 +366,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!{123};
|
||||
| ^^^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!{"{}", 123};
|
||||
| +++++
|
||||
@ -385,7 +385,7 @@ LL | panic!(v);
|
||||
| |
|
||||
| help: use std::panic::panic_any instead: `std::panic::panic_any`
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
|
||||
warning: panic message is not a string literal
|
||||
@ -394,7 +394,7 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, v);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
|
||||
warning: panic message is not a string literal
|
||||
@ -403,9 +403,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(v);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{:?}" format string to use the Debug implementation of `T`
|
||||
help: add a "{:?}" format string to use the `Debug` implementation of `T`
|
||||
|
|
||||
LL | panic!("{:?}", v);
|
||||
| +++++++
|
||||
@ -420,9 +420,9 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, v);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{:?}" format string to use the Debug implementation of `T`
|
||||
help: add a "{:?}" format string to use the `Debug` implementation of `T`
|
||||
|
|
||||
LL | assert!(false, "{:?}", v);
|
||||
| +++++++
|
||||
@ -433,9 +433,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(v);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!("{}", v);
|
||||
| +++++
|
||||
@ -450,9 +450,9 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, v);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | assert!(false, "{}", v);
|
||||
| +++++
|
||||
@ -463,9 +463,9 @@ warning: panic message is not a string literal
|
||||
LL | panic!(v);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | panic!("{}", v);
|
||||
| +++++
|
||||
@ -480,9 +480,9 @@ warning: panic message is not a string literal
|
||||
LL | assert!(false, v);
|
||||
| ^
|
||||
|
|
||||
= note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021
|
||||
= note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||
help: add a "{}" format string to Display the message
|
||||
help: add a "{}" format string to `Display` the message
|
||||
|
|
||||
LL | assert!(false, "{}", v);
|
||||
| +++++
|
||||
|
Loading…
x
Reference in New Issue
Block a user