diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl new file mode 100644 index 0000000000000000000000000000000000000000..e7e07093c0324db97a2b7c247f5800a4bb9f7c09 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -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::` + .suggestion = try using `ty::` 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 + .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., `::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} 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 diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index d52b94b78dfac035f1d227d3c385364bb4bc32cd..563d0534d8f388c460daccf53783a9a631d4ad5c 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -31,11 +31,12 @@ // 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}; diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f9fc526b5e4963b0fdc56174f25099779cb11cfc..c15dc024736f3ed0a0d3b8dd0b5bec8d8d49bae1 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -8,7 +8,7 @@ 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() diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 9e0a99849a3f4e3c7a80f6cddad253ac8792fe2e..1ad33ef25b763af5f27d12a62a25fc3cafd9c963 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -529,7 +529,7 @@ pub fn span_labels( applicability: Applicability, ) -> &mut Self); - forward!(pub fn set_primary_message(&mut self, msg: impl Into) -> &mut Self); + forward!(pub fn set_primary_message(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn set_span(&mut self, sp: impl Into) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); forward!(pub fn set_arg( diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index b33ab40eb39cb8a664a091b1aed39107bc6a8565..121fefdc6207a830041ea7b2d20c5f99a19b6986 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -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 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { _ => 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, ); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c0cf8c6b76b786c500ea8d3396aadad50fd5a05e..2fa4d7e072fef6c851df1826a977464a747d71bd 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -31,7 +31,9 @@ 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 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { 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 @@ fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) { 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 @@ fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) { == 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 @@ fn report_unsafe( 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 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { // 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 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { 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 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a `no_mangle` function", + fluent::lint::builtin_no_mangle_fn, ); } @@ -401,7 +396,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { 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 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { 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 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a `no_mangle` static", + fluent::lint::builtin_no_mangle_static, ); } @@ -427,7 +422,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { 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 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { 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 @@ fn check_impl_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { 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 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast { 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 @@ fn check_missing_docs_attrs( 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { .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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { 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 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { ("", 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 @@ pub fn new() -> 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 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { _, ) = 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { // 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { 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 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { 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 @@ fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { 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 @@ fn perform_lint( } 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 @@ struct WalkAssocTypes<'a> { 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., `::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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { 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 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { }; 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 @@ fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> }; 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 @@ fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> 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 @@ fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> } 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { 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 @@ fn check_ident_token( } 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 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { 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 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { .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 #{} \ - 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 @@ fn ty_find_init_error<'tcx>( 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 @@ fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignI 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 @@ fn is_zero(expr: &hir::Expr<'_>) -> bool { 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 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { 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 `:` should be used in inline asm" diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index c5e15a88fdf1c302a48d75dfc5795f9311613314..5d212768d0d8bf68c867fca07b71495867891c50 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -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(); }); } diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 95e3125045db4128e8a96eb7050acef4fcee21e7..699e81543188f4f44f5c674f8c228ade46986409 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -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(); diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index fc99d759a03f594d45afb1db5b2bf65eea5a4ba9..fe2712525eea5e2c6e3e73e487b2b2feff89ba14 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -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 @@ fn lint_text_direction_codepoint( .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 @@ fn lint_text_direction_codepoint( // 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::>() .join(", "), - )); + ); + err.note(fluent::lint::suggestion_remove); + err.note(fluent::lint::no_suggestion_note_escape); } err.emit(); }); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 56c8635a189e1be10e7d1562d680eab630cb81ce..5bcf9390c076a1adb41cf4025498a86c2d3190c6 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -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 @@ fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { _ => 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 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { 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 @@ fn check_path( 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::`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( span, - "try using `ty::` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -175,10 +169,10 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { - lint.build("usage of `ty::TyKind::`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( path.span, - "try using `ty::` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -193,10 +187,10 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { - lint.build("usage of `ty::TyKind::`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( path.span, - "try using `ty::` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -213,10 +207,10 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { - lint.build("usage of `ty::TyKind::`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( path.span, - "try using `ty::` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -226,15 +220,16 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { } _ => {} } - 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 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { 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 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { 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 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { 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(); }) } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 4773feded12fa300a31c791c0116b8534693310c..bf4a726b061881b86cc44147f6581241cf343734 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -521,7 +521,7 @@ pub(crate) fn push( 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 @@ pub(crate) fn push( } 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, diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index b6a45676a309373b8ff56ffd7d4800e01d42cbb4..ff5a01749c19e66b5246c514c6a71f2307fe8826 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -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(); }); } } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 6182d2b10ed5b183e6a9d4b295bb061a0fd26de5..764003e61a6dfb0991ee2c5c4c143417015fc0df 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -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 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { } 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 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { .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 @@ enum ScriptSetUsage { 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(); }); } } diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 4e7aeca9ce1d5c881baa52d404d08b349c4d4c01..cdad2d2e8f93e0d4bb18fa0c53032ef7bb085bfb 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -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 "); + 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, ); diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index e1507d0fbb48ff0525d7f68f08c44008e84dae33..33ac2ed02aa00c0ef89c222247d89a917f08ef18 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -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 @@ fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) { 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 @@ fn is_snake_case(ident: &str) -> bool { 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 @@ fn is_snake_case(ident: &str) -> bool { // 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 @@ fn is_snake_case(ident: &str) -> bool { 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 @@ fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) { 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(); }) } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 675bee738a672a313c78580618e10f5ba6ea33eb..2e847c8b89c56669827e72fb5530e6422da3279d 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -2,6 +2,7 @@ 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 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { ) { 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 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { 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(); }); } } diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 2c8b41d7214031459287c74e181eb42fcf310168..af5e5faf1f568aef60d44de98c57acafe0b69615 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -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 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { } 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, diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs index f06a8b8f4b0c3fb82b04b28dfb9cdf2f9dda66a7..26f41345383f91bad2218eca90e7048bd5385a51 100644 --- a/compiler/rustc_lint/src/redundant_semicolon.rs +++ b/compiler/rustc_lint/src/redundant_semicolon.rs @@ -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(); }); } } diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 81d308ee3470246a0829ab54ac5d8ab777e8284a..df1587c5948f58d4cf984e48e852f2cb65f3bc22 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -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 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { 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 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { 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(); }); } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 5579e4d19cf1fe5f30a25067b5a97f3e12ea3e12..0056872ee44c30e27cebaffa46fc80a081991329 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -2,7 +2,7 @@ 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 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) { 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 }, + FfiUnsafe { ty: Ty<'tcx>, reason: DiagnosticMessage, help: Option }, } pub(crate) fn nonnull_optimization_guaranteed<'tcx>( @@ -823,8 +824,8 @@ fn check_for_array_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { 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 @@ fn check_variant_for_ffi( } 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 @@ fn check_variant_for_ffi( 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F } 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F } 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F 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 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> F // 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 @@ fn emit_ffi_unsafe_type_lint( &mut self, ty: Ty<'tcx>, sp: Span, - note: &str, - help: Option<&str>, + note: DiagnosticMessage, + help: Option, ) { let lint = match self.mode { CItemKind::Declaration => IMPROPER_CTYPES, @@ -1160,18 +1160,17 @@ fn emit_ffi_unsafe_type_lint( 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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { } 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 @@ fn check_type_for_ffi_and_report_errors( 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 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { 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 @@ fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { { 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 @@ fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) { && 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 @@ fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) { 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 @@ fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) { 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(); }); } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 73f353e62c177e68da1db027bd4fc5f0a0cc973f..53269d18527033a8fbb0eb75c0afc0a6380e61ca 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -3,7 +3,7 @@ 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 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { 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 @@ fn check_must_use_ty<'tcx>( }, 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 @@ fn check_must_use_def( ) -> 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 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { 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 @@ fn emit_unused_delims( } 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 @@ fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: & }; 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 @@ fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { 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(); }); } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 215d8decf2a88f9c30ac6875069276d115601a91..32c0a7e260569986291f7b9878cf62b499d14a60 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -3,7 +3,8 @@ 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 fn new( 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) -> DiagnosticBuilder<'a, G> { self.0.set_primary_message(msg); self.0.set_is_lint(); self.0 diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f73eca5bf612cd4b888e3ec9cc69b727eb00e7fa..c71905b4aca7ff04a0ee14cfb3cb22f00d38eaf6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -611,6 +611,12 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas } } +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> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 845be2ab264a610b989b5615805b815fed589516..f22f3f61a01f2f18314fb13ee8cab7bef8ef4a4b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -550,7 +550,7 @@ fn recur( id, span, |lint| { - lint.build(&msg).emit(); + lint.build(msg).emit(); }, ); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 40545b19b24dc1364f55ec0301ea9ffe0efc9a18..8c123c052e5ac4aa941a7d79adfc6ed87218d53a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1163,7 +1163,7 @@ fn check_doc_attrs( hir_id, meta.span(), |lint| { - lint.build(&"invalid `doc` attribute").emit(); + lint.build("invalid `doc` attribute").emit(); }, ); is_valid = false; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d230c06a2112f87251f8063d95c3c0806cddc360..2895c923adc1346ab88baacdb60552e50adce212 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2356,6 +2356,9 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but /// with the argument order swapped. /// +/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy /// /// # Safety @@ -2461,6 +2464,9 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - /// order swapped. Copying takes place as if the bytes were copied from `src` /// to a temporary array and then copied from the array to `dst`. /// +/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove /// /// # Safety diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 970636c0cfcbbca2af6d86f08c04fd9bf094d9d8..4f257f9de3080295aff57eb316a8ed24abfc0552 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -730,7 +730,7 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// Swaps the values at two mutable locations of the same type, without /// deinitializing either. /// -/// But for the following two exceptions, this function is semantically +/// But for the following exceptions, this function is semantically /// equivalent to [`mem::swap`]: /// /// * It operates on raw pointers instead of references. When references are @@ -740,6 +740,9 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// overlapping region of memory from `x` will be used. This is demonstrated /// in the second example below. /// +/// * The operation is "untyped" in the sense that data may be uninitialized or otherwise violate +/// the requirements of `T`. The initialization state is preserved exactly. +/// /// # Safety /// /// Behavior is undefined if any of the following conditions are violated: @@ -816,6 +819,9 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// Swaps `count * size_of::()` bytes between the two regions of memory /// beginning at `x` and `y`. The two regions must *not* overlap. /// +/// The operation is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// /// # Safety /// /// Behavior is undefined if any of the following conditions are violated: @@ -861,15 +867,15 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { if mem::align_of::() >= mem::align_of::<$ChunkTy>() && mem::size_of::() % mem::size_of::<$ChunkTy>() == 0 { - let x: *mut MaybeUninit<$ChunkTy> = x.cast(); - let y: *mut MaybeUninit<$ChunkTy> = y.cast(); + let x: *mut $ChunkTy = x.cast(); + let y: *mut $ChunkTy = y.cast(); let count = count * (mem::size_of::() / mem::size_of::<$ChunkTy>()); // SAFETY: these are the same bytes that the caller promised were // ok, just typed as `MaybeUninit`s instead of as `T`s. // The `if` condition above ensures that we're not violating // alignment requirements, and that the division is exact so // that we don't lose any bytes off the end. - return unsafe { swap_nonoverlapping_simple(x, y, count) }; + return unsafe { swap_nonoverlapping_simple_untyped(x, y, count) }; } }; } @@ -902,7 +908,7 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { } // SAFETY: Same preconditions as this function - unsafe { swap_nonoverlapping_simple(x, y, count) } + unsafe { swap_nonoverlapping_simple_untyped(x, y, count) } } /// Same behaviour and safety conditions as [`swap_nonoverlapping`] @@ -911,17 +917,17 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// `swap_nonoverlapping` tries to use) so no need to manually SIMD it. #[inline] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] -const unsafe fn swap_nonoverlapping_simple(x: *mut T, y: *mut T, count: usize) { +const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, count: usize) { + let x = x.cast::>(); + let y = y.cast::>(); let mut i = 0; while i < count { - let x: &mut T = - // SAFETY: By precondition, `i` is in-bounds because it's below `n` - unsafe { &mut *x.add(i) }; - let y: &mut T = - // SAFETY: By precondition, `i` is in-bounds because it's below `n` - // and it's distinct from `x` since the ranges are non-overlapping - unsafe { &mut *y.add(i) }; - mem::swap_simple(x, y); + // SAFETY: By precondition, `i` is in-bounds because it's below `n` + let x = unsafe { &mut *x.add(i) }; + // SAFETY: By precondition, `i` is in-bounds because it's below `n` + // and it's distinct from `x` since the ranges are non-overlapping + let y = unsafe { &mut *y.add(i) }; + mem::swap_simple::>(x, y); i += 1; } diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index e49595c25edde9f31cfc6de30844b72a980c0586..bab2b1792f68093940d61c5d06644b9a746f4596 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -781,6 +781,31 @@ pub fn set_tag(&mut self, data: usize) { } } +#[test] +fn swap_copy_untyped() { + // We call `{swap,copy}{,_nonoverlapping}` at `bool` type on data that is not a valid bool. + // These should all do untyped copies, so this should work fine. + let mut x = 5u8; + let mut y = 6u8; + + let ptr1 = &mut x as *mut u8 as *mut bool; + let ptr2 = &mut y as *mut u8 as *mut bool; + + unsafe { + ptr::swap(ptr1, ptr2); + ptr::swap_nonoverlapping(ptr1, ptr2, 1); + } + assert_eq!(x, 5); + assert_eq!(y, 6); + + unsafe { + ptr::copy(ptr1, ptr2, 1); + ptr::copy_nonoverlapping(ptr1, ptr2, 1); + } + assert_eq!(x, 5); + assert_eq!(y, 5); +} + #[test] fn test_const_copy() { const { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 8d99b85bebecec01810312404083d6ba6c613a08..b3dc60d880bbf4d774f80e95dd790efa84fad92b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1739,6 +1739,11 @@ details.rustdoc-toggle[open] > summary.hideme::after { /* Media Queries */ +/* +WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY; +If you update this line, then you also need to update the line with the same warning +in storage.js plus the media query with (max-width: 700px) +*/ @media (min-width: 701px) { /* In case there is no documentation before a code block, we need to add some margin at the top to prevent an overlay between the "collapse toggle" and the information tooltip. @@ -1759,6 +1764,11 @@ details.rustdoc-toggle[open] > summary.hideme::after { } } +/* +WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY +If you update this line, then you also need to update the line with the same warning +in storage.js plus the media query with (min-width: 701px) +*/ @media (max-width: 700px) { /* When linking to an item with an `id` (for instance, by clicking a link in the sidebar, or visiting a URL with a fragment like `#method.new`, we don't want the item to be obscured diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index 45e70c9a7c721d326f0486c64b691b47f25121e8..1e9bfa5cc89594a8a3050c26e6716004c1207927 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -12,6 +12,12 @@ const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value; let oldScrollPosition = 0; +function closeSidebarIfMobile() { + if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { + updateLocalStorage("source-sidebar-show", "false"); + } +} + function createDirEntry(elem, parent, fullPath, hasFoundFile) { const dirEntry = document.createElement("details"); const summary = document.createElement("summary"); @@ -42,6 +48,7 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) { const file = document.createElement("a"); file.innerText = file_text; file.href = rootPath + "src/" + fullPath + file_text + ".html"; + file.addEventListener("click", closeSidebarIfMobile); const w = window.location.href.split("#")[0]; if (!hasFoundFile && w === file.href) { file.className = "selected"; @@ -59,7 +66,7 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) { function toggleSidebar() { const child = this.parentNode.children[0]; if (child.innerText === ">") { - if (window.innerWidth < 701) { + if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { // This is to keep the scroll position on mobile. oldScrollPosition = window.scrollY; document.body.style.position = "fixed"; @@ -69,7 +76,7 @@ function toggleSidebar() { child.innerText = "<"; updateLocalStorage("source-sidebar-show", "true"); } else { - if (window.innerWidth < 701) { + if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { // This is to keep the scroll position on mobile. document.body.style.position = ""; document.body.style.top = ""; diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 1c4c88344888cf28dd6c6aca00d3fcae540790d2..0c5389d45e5b7aa1bca73c66af049a09cd59625a 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -9,6 +9,11 @@ const darkThemes = ["dark", "ayu"]; window.currentTheme = document.getElementById("themeStyle"); window.mainTheme = document.getElementById("mainThemeStyle"); +// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY +// If you update this line, then you also need to update the two media queries with the same +// warning in rustdoc.css +window.RUSTDOC_MOBILE_BREAKPOINT = 701; + const settingsDataset = (function() { const settingsElement = document.getElementById("default-settings"); if (settingsElement === null) { diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index 25699d82e61decf49c939fa9b277a8b2213cd745..fa322574fdec7bd7140a1c2d32f238d1b565c385 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -18,6 +18,17 @@ click: "#sidebar-toggle" // Because of the transition CSS, we check by using `wait-for-css` instead of `assert-css`. wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) +// We now check that opening the sidebar and clicking a link will leave it open. +// The behavior here on desktop is different than the behavior on mobile, +// but since the sidebar doesn't fill the entire screen here, it makes sense to have the +// sidebar stay resident. +wait-for-css: (".sidebar", {"width": "300px"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} +click: ".sidebar a.selected" +goto: file://|DOC_PATH|/src/test_docs/lib.rs.html +wait-for-css: (".sidebar", {"width": "300px"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} + // Now we check the display of the sidebar items. show-text: true @@ -221,3 +232,23 @@ click: "#sidebar-toggle" wait-for-css: (".sidebar", {"width": "0px"}) // The "scrollTop" property should be the same. assert-window-property: {"pageYOffset": "2519"} + +// We now check that opening the sidebar and clicking a link will close it. +// The behavior here on mobile is different than the behavior on desktop, +// but common sense dictates that if you have a list of files that fills the entire screen, and +// you click one of them, you probably want to actually see the file's contents, and not just +// make it the current selection. +click: "#sidebar-toggle" +wait-for-css: ("#source-sidebar", {"visibility": "visible"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} +click: ".sidebar a.selected" +goto: file://|DOC_PATH|/src/test_docs/lib.rs.html +wait-for-css: ("#source-sidebar", {"visibility": "hidden"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "false"} +// Resize back to desktop size, to check that the sidebar doesn't spontaneously open. +size: (1000, 1000) +wait-for-css: ("#source-sidebar", {"visibility": "hidden"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "false"} +click: "#sidebar-toggle" +wait-for-css: ("#source-sidebar", {"visibility": "visible"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} diff --git a/src/test/rustdoc/intra-doc/pub-use.rs b/src/test/rustdoc/intra-doc/pub-use.rs index 0c70cdee91462aacf6fcb4d1d6499b7d1f451e53..8a998496cf56b848d6c2d2d81ac5da60b12722d3 100644 --- a/src/test/rustdoc/intra-doc/pub-use.rs +++ b/src/test/rustdoc/intra-doc/pub-use.rs @@ -5,21 +5,11 @@ extern crate inner; /// [mod@std::env] [g] - -// FIXME: This can't be tested because rustdoc doesn't show documentation on pub re-exports. -// Until then, comment out the `htmldocck` test. -// This test still does something; namely check that no incorrect errors are emitted when -// documenting the re-export. - // @has outer/index.html -// @ has - '//a[@href="{{channel}}/std/env/fn.var.html"]' "std::env" -// @ has - '//a[@href="fn.f.html"]' "g" +// @has - '//a[@href="{{channel}}/std/env/index.html"]' "std::env" +// @has - '//a[@href="fn.f.html"]' "g" pub use f as g; -// FIXME: same as above -/// [std::env] -extern crate self as _; - // Make sure the documentation is actually correct by documenting an inlined re-export /// [mod@std::env] // @has outer/fn.f.html diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr index bac44f338b74c04fc2a575d02253a544911b6913..bc9fcdd7bc7a56a54014e3746a437ae3e73b3de5 100644 --- a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr +++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr @@ -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")] diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 7bec1897fa53e56fd637ba4e8d9682dcb515d4d6..18283c19cb42c1733e1f87abfd93e108101a263f 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -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: diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 0d9690e1f5a998437943d7715c784956bd8fa2f0..9e2e34e4bec81b8558f03a7e87e6f557a826c3d1 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -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 | diff --git a/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr index 94cf64fff1999a5a2d2ada2292d8b74d946bae3f..f06dedc229845bd02b500b5daa8bce0d8aa62c0c 100644 --- a/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr +++ b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr @@ -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 -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!("{}", { "foo" }); | +++++ diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr index 4da97ed5d60eb481bb12bbb0e075e77b5b796a7f..6e4434e6f33723fc2fec20d72c240e6c7515bf92 100644 --- a/src/test/ui/non-fmt-panic.stderr +++ b/src/test/ui/non-fmt-panic.stderr @@ -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 -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 -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 -help: add a "{:?}" format string to use the Debug implementation of `Option` +help: add a "{:?}" format string to use the `Debug` implementation of `Option` | 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 -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 -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 -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 -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 -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 -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 -help: add a "{:?}" format string to use the Debug implementation of `Option` +help: add a "{:?}" format string to use the `Debug` implementation of `Option` | 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 -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 -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 - = 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 - = 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 - = 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 - = 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 -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 -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 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 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 -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 -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 -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 -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 -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 -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | assert!(false, "{}", v); | +++++ diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index b74e96f509baf0be70281c55f14cb18fefbc6b22..75b22326dad1914c22484ab6672de5cae94f7457 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit b74e96f509baf0be70281c55f14cb18fefbc6b22 +Subproject commit 75b22326dad1914c22484ab6672de5cae94f7457