summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_lint
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_lint')
-rw-r--r--compiler/rustc_lint/locales/en-US.ftl510
-rw-r--r--compiler/rustc_lint/src/array_into_iter.rs6
-rw-r--r--compiler/rustc_lint/src/builtin.rs187
-rw-r--r--compiler/rustc_lint/src/context.rs42
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs2
-rw-r--r--compiler/rustc_lint/src/enum_intrinsics_non_enums.rs2
-rw-r--r--compiler/rustc_lint/src/errors.rs6
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs10
-rw-r--r--compiler/rustc_lint/src/internal.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs15
-rw-r--r--compiler/rustc_lint/src/levels.rs17
-rw-r--r--compiler/rustc_lint/src/lib.rs24
-rw-r--r--compiler/rustc_lint/src/lints.rs172
-rw-r--r--compiler/rustc_lint/src/map_unit_fn.rs120
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs60
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs20
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs18
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs2
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_lint/src/passes.rs3
-rw-r--r--compiler/rustc_lint/src/types.rs47
-rw-r--r--compiler/rustc_lint/src/unused.rs28
22 files changed, 1075 insertions, 220 deletions
diff --git a/compiler/rustc_lint/locales/en-US.ftl b/compiler/rustc_lint/locales/en-US.ftl
new file mode 100644
index 000000000..68e62c978
--- /dev/null
+++ b/compiler/rustc_lint/locales/en-US.ftl
@@ -0,0 +1,510 @@
+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
+ .rationale = {$rationale}
+
+lint_for_loops_over_fallibles =
+ for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement
+ .suggestion = consider using `if let` to clear intent
+ .remove_next = to iterate over `{$recv_snip}` remove the call to `next`
+ .use_while_let = to check pattern in a loop use `while let`
+ .use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents
+
+lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
+ .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+ .function_label = this function returns `()`, which is likely not what you wanted
+ .argument_label = called `Iterator::map` with callable that returns `()`
+ .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+ .suggestion = you might have meant to use `Iterator::for_each`
+
+lint_non_binding_let_on_sync_lock =
+ non-binding let on a synchronization lock
+
+lint_non_binding_let_on_drop_type =
+ non-binding let on a type that implements `Drop`
+
+lint_non_binding_let_suggestion =
+ consider binding to an unused variable to avoid immediately dropping the value
+
+lint_non_binding_let_multi_suggestion =
+ consider immediately dropping the value
+
+lint_deprecated_lint_name =
+ lint name `{$name}` is deprecated and may not have an effect in the future.
+ .suggestion = change it to
+
+lint_renamed_or_removed_lint = {$msg}
+ .suggestion = use the new name
+
+lint_unknown_lint =
+ unknown lint: `{$name}`
+ .suggestion = did you mean
+
+lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
+
+lint_unknown_gated_lint =
+ unknown lint: `{$name}`
+ .note = the `{$name}` lint is unstable
+
+lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label}
+ .label = this {$label} contains {$count ->
+ [one] an invisible
+ *[other] invisible
+ } unicode text flow control {$count ->
+ [one] codepoint
+ *[other] codepoints
+ }
+ .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ .suggestion_remove = if their presence wasn't intentional, you can remove them
+ .suggestion_escape = if you want to keep them but make them visible in your source code, you can escape them
+ .no_suggestion_note_escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped}
+
+lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
+ .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
+
+lint_query_instability = using `{$query}` can result in unstable query results
+ .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
+
+lint_tykind_kind = usage of `ty::TyKind::<kind>`
+ .suggestion = try using `ty::<kind>` directly
+
+lint_tykind = usage of `ty::TyKind`
+ .help = try using `Ty` instead
+
+lint_ty_qualified = usage of qualified `ty::{$ty}`
+ .suggestion = try importing it and using it unqualified
+
+lint_lintpass_by_hand = implementing `LintPass` by hand
+ .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
+
+lint_non_existant_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = \"...\")]`
+ .help = only existing keywords are allowed in core/std
+
+lint_diag_out_of_impl =
+ diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+
+lint_untranslatable_diag = diagnostics should be created using translatable messages
+
+lint_bad_opt_access = {$msg}
+
+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_multple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
+
+lint_identifier_non_ascii_char = identifier contains non-ASCII characters
+
+lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
+
+lint_confusable_identifier_pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
+ .label = this is where the previous identifier occurred
+
+lint_mixed_script_confusables =
+ the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
+ .includes_note = the usage includes {$includes}
+ .note = please recheck to make sure their usages are indeed what you want
+
+lint_non_fmt_panic = panic message is not a string literal
+ .note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021
+ .more_info_note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
+ .supports_fmt_note = the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here
+ .supports_fmt_suggestion = remove the `format!(..)` macro call
+ .display_suggestion = add a "{"{"}{"}"}" format string to `Display` the message
+ .debug_suggestion =
+ add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}`
+ .panic_suggestion = {$already_suggested ->
+ [true] or use
+ *[false] use
+ } std::panic::panic_any instead
+
+lint_non_fmt_panic_unused =
+ panic message contains {$count ->
+ [one] an unused
+ *[other] unused
+ } formatting {$count ->
+ [one] placeholder
+ *[other] placeholders
+ }
+ .note = this message is not used as a format string when given without arguments, but will be in Rust 2021
+ .add_args_suggestion = add the missing {$count ->
+ [one] argument
+ *[other] arguments
+ }
+ .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
+
+lint_non_fmt_panic_braces =
+ panic message contains {$count ->
+ [one] a brace
+ *[other] braces
+ }
+ .note = this message is not used as a format string, but will be in Rust 2021
+ .suggestion = add a "{"{"}{"}"}" format string to use the message literally
+
+lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name
+ .suggestion = convert the identifier to upper camel case
+ .label = should have an UpperCamelCase name
+
+lint_non_snake_case = {$sort} `{$name}` should have a snake case name
+ .rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier
+ .cannot_convert_note = `{$sc}` cannot be used as a raw identifier
+ .rename_suggestion = rename the identifier
+ .convert_suggestion = convert the identifier to snake case
+ .help = convert the identifier to snake case: `{$sc}`
+ .label = should have a snake_case name
+
+lint_non_upper_case_global = {$sort} `{$name}` should have an upper case name
+ .suggestion = convert the identifier to upper case
+ .label = should have an UPPER_CASE name
+
+lint_noop_method_call = call to `.{$method}()` on a reference in this situation does nothing
+ .label = unnecessary method call
+ .note = the type `{$receiver_ty}` which `{$method}` is being called on is the same as the type returned from `{$method}`, so the method call does not do anything and can be removed
+
+lint_pass_by_value = passing `{$ty}` by reference
+ .suggestion = try passing by value
+
+lint_redundant_semicolons =
+ unnecessary trailing {$multiple ->
+ [true] semicolons
+ *[false] semicolon
+ }
+ .suggestion = remove {$multiple ->
+ [true] these semicolons
+ *[false] this semicolon
+ }
+
+lint_drop_trait_constraints =
+ bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
+
+lint_drop_glue =
+ types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
+
+lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
+ .suggestion = use an inclusive range instead
+
+lint_overflowing_bin_hex = literal out of range for `{$ty}`
+ .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
+ .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`
+ .positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`
+ .suggestion = consider using the type `{$suggestion_ty}` instead
+ .help = consider using the type `{$suggestion_ty}` instead
+
+lint_overflowing_int = literal out of range for `{$ty}`
+ .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
+ .help = consider using the type `{$suggestion_ty}` instead
+
+lint_only_cast_u8_to_char = only `u8` can be cast into `char`
+ .suggestion = use a `char` literal instead
+
+lint_overflowing_uint = literal out of range for `{$ty}`
+ .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
+
+lint_overflowing_literal = literal out of range for `{$ty}`
+ .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
+
+lint_unused_comparisons = comparison is useless due to type limits
+
+lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
+ .label = not FFI-safe
+ .note = the type is defined here
+
+lint_improper_ctypes_opaque = opaque types have no C equivalent
+
+lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
+lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
+
+lint_improper_ctypes_tuple_reason = tuples have unspecified layout
+lint_improper_ctypes_tuple_help = consider using a struct instead
+
+lint_improper_ctypes_str_reason = string slices have no C equivalent
+lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
+
+lint_improper_ctypes_dyn = trait objects have no C equivalent
+
+lint_improper_ctypes_slice_reason = slices have no C equivalent
+lint_improper_ctypes_slice_help = consider using a raw pointer instead
+
+lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
+
+lint_improper_ctypes_char_reason = the `char` type has no C equivalent
+lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
+
+lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
+lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
+
+lint_improper_ctypes_enum_repr_reason = enum has no representation hint
+lint_improper_ctypes_enum_repr_help =
+ consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+
+lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
+lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
+
+lint_improper_ctypes_union_fieldless_reason = this union has no fields
+lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
+
+lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
+lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
+
+lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
+lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+
+lint_improper_ctypes_union_layout_reason = this union has unspecified layout
+lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+
+lint_improper_ctypes_box = box cannot be represented as a single pointer
+
+lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
+
+lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
+
+lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
+lint_improper_ctypes_array_help = consider passing a pointer to the array
+
+lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
+
+lint_variant_size_differences =
+ enum variant is more than three times larger ({$largest} bytes) than the next largest
+
+lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering
+ .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+
+lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
+ .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
+
+lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
+ .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
+
+lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
+ .label = invalid failure ordering
+ .help = consider using `Acquire` or `Relaxed` failure ordering instead
+
+lint_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
+ .suggestion = use `let _ = ...` to ignore the resulting value
+
+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}
+ .msg_suggestion = {$msg}
+ .default_suggestion = remove this attribute
+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_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
+ .label = this function will not propagate the caller location
+
+lint_builtin_unreachable_pub = unreachable `pub` {$what}
+ .suggestion = consider restricting its visibility
+ .help = or consider exporting it for use by other crates
+
+lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
+
+lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
+
+lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
+ .suggestion = the clause will not be checked when the type alias is used, and should be removed
+
+lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
+ .suggestion = the bound will not be checked when the type alias is used, and should be removed
+
+lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
+
+lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
+ .suggestion = use `..=` for an inclusive range
+
+lint_builtin_unnameable_test_items = cannot test inner items
+
+lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition
+ .suggestion = you can use a raw identifier to stay compatible
+
+lint_builtin_explicit_outlives = outlives requirements can be inferred
+ .suggestion = remove {$count ->
+ [one] this bound
+ *[other] these bounds
+ }
+
+lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
+ .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
+ .help = consider using `min_{$name}` instead, which is more stable and complete
+
+lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
+lint_builtin_unpermitted_type_init_unint = the type `{$ty}` does not permit being left uninitialized
+
+lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
+lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+
+lint_builtin_clashing_extern_same_name = `{$this}` 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}` 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
+
+lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
+ .note = lib.rs is the root of this crate's library target
+ .help = to refer to it from other targets, use the library's name as the path
+
+lint_builtin_special_module_name_used_main = found module declaration for main.rs
+ .note = a binary crate cannot be used as library
+
+lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
+ .label = target type is set here
+
+lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
+ .label = overruled by previous forbid
+
+lint_default_source = `forbid` lint level is the default for {$id}
+
+lint_node_source = `forbid` level set here
+ .note = {$reason}
+
+lint_command_line_source = `forbid` lint level was set on command line
+
+lint_malformed_attribute = malformed lint attribute input
+
+lint_bad_attribute_argument = bad attribute argument
+
+lint_reason_must_be_string_literal = reason must be a string literal
+
+lint_reason_must_come_last = reason in lint attribute must come last
+
+lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
+ .help = add `#![register_tool({$tool_name})]` to the crate root
+
+lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
+
+lint_requested_level = requested on the command line with `{$level} {$lint_name}`
+
+lint_check_name_unknown = unknown lint: `{$lint_name}`
+ .help = did you mean: `{$suggestion}`
+
+lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
+
+lint_check_name_warning = {$msg}
+
+lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
+
+lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
+ .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
+
+lint_opaque_hidden_inferred_bound_sugg = add this bound
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index 3593f141d..bccb0a94e 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -1,5 +1,7 @@
-use crate::lints::{ArrayIntoIterDiag, ArrayIntoIterDiagSub};
-use crate::{LateContext, LateLintPass, LintContext};
+use crate::{
+ lints::{ArrayIntoIterDiag, ArrayIntoIterDiagSub},
+ LateContext, LateLintPass, LintContext,
+};
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index fe188162c..5b2100b5d 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -20,6 +20,7 @@
//! If you define a new `LateLintPass`, you will also need to add it to the
//! `late_lint_methods!` invocation in `lib.rs`.
+use crate::fluent_generated as fluent;
use crate::{
errors::BuiltinEllpisisInclusiveRangePatterns,
lints::{
@@ -50,15 +51,13 @@ use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust::{self, expr_to_string};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_errors::{fluent, Applicability, DecorateLint, MultiSpan};
+use rustc_errors::{Applicability, DecorateLint, MultiSpan};
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
use rustc_hir::intravisit::FnKind as HirFnKind;
-use rustc_hir::{
- Body, FnDecl, ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin,
-};
+use rustc_hir::{Body, FnDecl, ForeignItemKind, GenericParamKind, Node, PatKind, PredicateOrigin};
use rustc_index::vec::Idx;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
@@ -185,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
| hir::ItemKind::Enum(..)
| hir::ItemKind::Struct(..)
| hir::ItemKind::Union(..) => {
- self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id))
+ self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id).subst_identity())
}
_ => (),
}
@@ -194,7 +193,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
match it.kind {
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
for field in struct_def.fields() {
- self.check_heap_type(cx, field.span, cx.tcx.type_of(field.def_id));
+ self.check_heap_type(
+ cx,
+ field.span,
+ cx.tcx.type_of(field.def_id).subst_identity(),
+ );
}
}
_ => (),
@@ -582,26 +585,28 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
- // If the method is an impl for a trait, don't doc.
- if method_context(cx, impl_item.hir_id()) == MethodLateContext::TraitImpl {
- return;
- }
-
- // If the method is an impl for an item with docs_hidden, don't doc.
- if method_context(cx, impl_item.hir_id()) == MethodLateContext::PlainImpl {
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
- let impl_ty = cx.tcx.type_of(parent);
- let outerdef = match impl_ty.kind() {
- ty::Adt(def, _) => Some(def.did()),
- ty::Foreign(def_id) => Some(*def_id),
- _ => None,
- };
- let is_hidden = match outerdef {
- Some(id) => cx.tcx.is_doc_hidden(id),
- None => false,
- };
- if is_hidden {
- return;
+ let context = method_context(cx, impl_item.owner_id.def_id);
+
+ match context {
+ // If the method is an impl for a trait, don't doc.
+ MethodLateContext::TraitImpl => return,
+ MethodLateContext::TraitAutoImpl => {}
+ // If the method is an impl for an item with docs_hidden, don't doc.
+ MethodLateContext::PlainImpl => {
+ let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let impl_ty = cx.tcx.type_of(parent).subst_identity();
+ let outerdef = match impl_ty.kind() {
+ ty::Adt(def, _) => Some(def.did()),
+ ty::Foreign(def_id) => Some(*def_id),
+ _ => None,
+ };
+ let is_hidden = match outerdef {
+ Some(id) => cx.tcx.is_doc_hidden(id),
+ None => false,
+ };
+ if is_hidden {
+ return;
+ }
}
}
@@ -672,21 +677,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
- (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
+ (def, cx.tcx.mk_adt(def, ty::List::empty()))
}
hir::ItemKind::Union(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
- (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
+ (def, cx.tcx.mk_adt(def, ty::List::empty()))
}
hir::ItemKind::Enum(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
- (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
+ (def, cx.tcx.mk_adt(def, ty::List::empty()))
}
_ => return,
};
@@ -698,7 +703,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
// and recommending Copy might be a bad idea.
for field in def.all_fields() {
let did = field.did;
- if cx.tcx.type_of(did).is_unsafe_ptr() {
+ if cx.tcx.type_of(did).subst_identity().is_unsafe_ptr() {
return;
}
}
@@ -732,7 +737,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
cx.tcx,
param_env,
ty,
- traits::ObligationCause::misc(item.span, item.hir_id()),
+ traits::ObligationCause::misc(item.span, item.owner_id.def_id),
)
.is_ok()
{
@@ -798,7 +803,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
if self.impling_types.is_none() {
let mut impls = LocalDefIdSet::default();
cx.tcx.for_each_impl(debug, |d| {
- if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
+ if let Some(ty_def) = cx.tcx.type_of(d).subst_identity().ty_adt_def() {
if let Some(def_id) = ty_def.did().as_local() {
impls.insert(def_id);
}
@@ -1283,7 +1288,7 @@ declare_lint! {
}
declare_lint_pass!(
- /// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
+ /// Explains corresponding feature flag must be enabled for the `#[track_caller]` attribute to
/// do anything
UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
);
@@ -1296,19 +1301,18 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
_: &'tcx FnDecl<'_>,
_: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if fn_kind.asyncness() == IsAsync::Async
&& !cx.tcx.features().closure_track_caller
- && let attrs = cx.tcx.hir().attrs(hir_id)
// Now, check if the function has the `#[track_caller]` attribute
- && let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller))
- {
- cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller {
- label: span,
- parse_sess: &cx.tcx.sess.parse_sess,
- });
- }
+ && let Some(attr) = cx.tcx.get_attr(def_id.to_def_id(), sym::track_caller)
+ {
+ cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller {
+ label: span,
+ parse_sess: &cx.tcx.sess.parse_sess,
+ });
+ }
}
}
@@ -1580,7 +1584,7 @@ declare_lint_pass!(
impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
- use rustc_middle::ty::visit::TypeVisitable;
+ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::Clause;
use rustc_middle::ty::PredicateKind::*;
@@ -1592,15 +1596,19 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
Clause(Clause::TypeOutlives(..)) |
Clause(Clause::RegionOutlives(..)) => "lifetime",
+ // `ConstArgHasType` is never global as `ct` is always a param
+ Clause(Clause::ConstArgHasType(..)) |
// Ignore projections, as they can only be global
// if the trait bound is global
Clause(Clause::Projection(..)) |
+ AliasEq(..) |
// Ignore bounds that a user can't type
WellFormed(..) |
ObjectSafe(..) |
ClosureKind(..) |
Subtype(..) |
Coerce(..) |
+ // FIXME(generic_const_exprs): `ConstEvaluatable` can be written
ConstEvaluatable(..) |
ConstEquate(..) |
Ambiguous |
@@ -2006,7 +2014,7 @@ impl ExplicitOutlivesRequirements {
inferred_outlives: &[ty::Region<'tcx>],
predicate_span: Span,
) -> Vec<(usize, Span)> {
- use rustc_middle::middle::resolve_lifetime::Region;
+ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
bounds
.iter()
@@ -2016,8 +2024,8 @@ impl ExplicitOutlivesRequirements {
return None;
};
- let is_inferred = match tcx.named_region(lifetime.hir_id) {
- Some(Region::EarlyBound(def_id)) => inferred_outlives
+ let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
+ Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
.iter()
.any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
_ => false,
@@ -2096,7 +2104,7 @@ impl ExplicitOutlivesRequirements {
impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
- use rustc_middle::middle::resolve_lifetime::Region;
+ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
let def_id = item.owner_id.def_id;
if let hir::ItemKind::Struct(_, hir_generics)
@@ -2119,8 +2127,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
match where_predicate {
hir::WherePredicate::RegionPredicate(predicate) => {
- if let Some(Region::EarlyBound(region_def_id)) =
- cx.tcx.named_region(predicate.lifetime.hir_id)
+ if let Some(ResolvedArg::EarlyBound(region_def_id)) =
+ cx.tcx.named_bound_var(predicate.lifetime.hir_id)
{
(
Self::lifetimes_outliving_lifetime(
@@ -2175,13 +2183,31 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
dropped_predicate_count += 1;
}
- if drop_predicate && !in_where_clause {
- lint_spans.push(predicate_span);
- } else if drop_predicate && i + 1 < num_predicates {
- // If all the bounds on a predicate were inferable and there are
- // further predicates, we want to eat the trailing comma.
- let next_predicate_span = hir_generics.predicates[i + 1].span();
- where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo()));
+ if drop_predicate {
+ if !in_where_clause {
+ lint_spans.push(predicate_span);
+ } else if predicate_span.from_expansion() {
+ // Don't try to extend the span if it comes from a macro expansion.
+ where_lint_spans.push(predicate_span);
+ } else if i + 1 < num_predicates {
+ // If all the bounds on a predicate were inferable and there are
+ // further predicates, we want to eat the trailing comma.
+ let next_predicate_span = hir_generics.predicates[i + 1].span();
+ if next_predicate_span.from_expansion() {
+ where_lint_spans.push(predicate_span);
+ } else {
+ where_lint_spans
+ .push(predicate_span.to(next_predicate_span.shrink_to_lo()));
+ }
+ } else {
+ // Eat the optional trailing comma after the last predicate.
+ let where_span = hir_generics.where_clause_span;
+ if where_span.from_expansion() {
+ where_lint_spans.push(predicate_span);
+ } else {
+ where_lint_spans.push(predicate_span.to(where_span.shrink_to_hi()));
+ }
+ }
} else {
where_lint_spans.extend(self.consolidate_outlives_bound_spans(
predicate_span.shrink_to_lo(),
@@ -2225,6 +2251,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
Applicability::MaybeIncorrect
};
+ // Due to macros, there might be several predicates with the same span
+ // and we only want to suggest removing them once.
+ lint_spans.sort_unstable();
+ lint_spans.dedup();
+
cx.emit_spanned_lint(
EXPLICIT_OUTLIVES_REQUIREMENTS,
lint_spans.clone(),
@@ -2284,11 +2315,8 @@ impl EarlyLintPass for IncompleteFeatures {
.for_each(|(&name, &span)| {
let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
.map(|n| BuiltinIncompleteFeaturesNote { n });
- let help = if HAS_MIN_FEATURES.contains(&name) {
- Some(BuiltinIncompleteFeaturesHelp)
- } else {
- None
- };
+ let help =
+ HAS_MIN_FEATURES.contains(&name).then_some(BuiltinIncompleteFeaturesHelp);
cx.emit_spanned_lint(
INCOMPLETE_FEATURES,
span,
@@ -2581,7 +2609,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
}
Array(ty, len) => {
- if matches!(len.try_eval_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
+ if matches!(len.try_eval_target_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
// Array length known at array non-empty -- recurse.
ty_find_init_error(cx, *ty, init)
} else {
@@ -2608,7 +2636,13 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
cx.emit_spanned_lint(
INVALID_VALUE,
expr.span,
- BuiltinUnpermittedTypeInit { msg, ty: conjured_ty, label: expr.span, sub },
+ BuiltinUnpermittedTypeInit {
+ msg,
+ ty: conjured_ty,
+ label: expr.span,
+ sub,
+ tcx: cx.tcx,
+ },
);
}
}
@@ -2661,7 +2695,7 @@ pub struct ClashingExternDeclarations {
/// the symbol should be reported as a clashing declaration.
// FIXME: Technically, we could just store a &'tcx str here without issue; however, the
// `impl_lint_pass` macro doesn't currently support lints parametric over a lifetime.
- seen_decls: FxHashMap<Symbol, HirId>,
+ seen_decls: FxHashMap<Symbol, hir::OwnerId>,
}
/// Differentiate between whether the name for an extern decl came from the link_name attribute or
@@ -2687,19 +2721,20 @@ impl ClashingExternDeclarations {
pub(crate) fn new() -> Self {
ClashingExternDeclarations { seen_decls: FxHashMap::default() }
}
+
/// Insert a new foreign item into the seen set. If a symbol with the same name already exists
/// for the item, return its HirId without updating the set.
- fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> {
+ fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<hir::OwnerId> {
let did = fi.owner_id.to_def_id();
let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
let name = Symbol::intern(tcx.symbol_name(instance).name);
- if let Some(&hir_id) = self.seen_decls.get(&name) {
+ if let Some(&existing_id) = self.seen_decls.get(&name) {
// Avoid updating the map with the new entry when we do find a collision. We want to
// make sure we're always pointing to the first definition as the previous declaration.
// This lets us avoid emitting "knock-on" diagnostics.
- Some(hir_id)
+ Some(existing_id)
} else {
- self.seen_decls.insert(name, fi.hir_id())
+ self.seen_decls.insert(name, fi.owner_id)
}
}
@@ -2830,8 +2865,8 @@ impl ClashingExternDeclarations {
structurally_same_type_impl(
seen_types,
cx,
- tcx.type_of(a_did),
- tcx.type_of(b_did),
+ tcx.type_of(a_did).subst_identity(),
+ tcx.type_of(b_did).subst_identity(),
ckind,
)
},
@@ -2926,16 +2961,16 @@ impl ClashingExternDeclarations {
impl_lint_pass!(ClashingExternDeclarations => [CLASHING_EXTERN_DECLARATIONS]);
impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
+ #[instrument(level = "trace", skip(self, cx))]
fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignItem<'_>) {
- trace!("ClashingExternDeclarations: check_foreign_item: {:?}", this_fi);
if let ForeignItemKind::Fn(..) = this_fi.kind {
let tcx = cx.tcx;
- if let Some(existing_hid) = self.insert(tcx, this_fi) {
- let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid));
- let this_decl_ty = tcx.type_of(this_fi.owner_id);
+ if let Some(existing_did) = self.insert(tcx, this_fi) {
+ let existing_decl_ty = tcx.type_of(existing_did).skip_binder();
+ let this_decl_ty = tcx.type_of(this_fi.owner_id).subst_identity();
debug!(
"ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
- existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty
+ existing_did, existing_decl_ty, this_fi.owner_id, this_decl_ty
);
// Check that the declarations match.
if !Self::structurally_same_type(
@@ -2944,7 +2979,7 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
this_decl_ty,
CItemKind::Declaration,
) {
- let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner());
+ let orig_fi = tcx.hir().expect_foreign_item(existing_did);
let orig = Self::name_of_extern_decl(tcx, orig_fi);
// We want to ensure that we use spans for both decls that include where the
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 8046cc21c..f5a711315 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -39,7 +39,7 @@ use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools,
use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
use rustc_session::Session;
-use rustc_span::lev_distance::find_best_match_for_name;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, Span};
use rustc_target::abi;
@@ -487,7 +487,7 @@ impl LintStore {
let mut groups: Vec<_> = self
.lint_groups
.iter()
- .filter_map(|(k, LintGroup { depr, .. })| if depr.is_none() { Some(k) } else { None })
+ .filter_map(|(k, LintGroup { depr, .. })| depr.is_none().then_some(k))
.collect();
groups.sort();
let groups = groups.iter().map(|k| Symbol::intern(k));
@@ -837,9 +837,17 @@ pub trait LintContext: Sized {
(use_span, "'_".to_owned())
};
debug!(?deletion_span, ?use_span);
+
+ // issue 107998 for the case such as a wrong function pointer type
+ // `deletion_span` is empty and there is no need to report lifetime uses here
+ let suggestions = if deletion_span.is_empty() {
+ vec![(use_span, replace_lt)]
+ } else {
+ vec![(deletion_span, String::new()), (use_span, replace_lt)]
+ };
db.multipart_suggestion(
msg,
- vec![(deletion_span, String::new()), (use_span, replace_lt)],
+ suggestions,
Applicability::MachineApplicable,
);
}
@@ -882,6 +890,26 @@ pub trait LintContext: Sized {
);
}
}
+ BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive => {
+ db.help("consider implementing the trait by hand, or remove the `packed` attribute");
+ }
+ BuiltinLintDiagnostics::UnusedExternCrate { removal_span }=> {
+ db.span_suggestion(
+ removal_span,
+ "remove it",
+ "",
+ Applicability::MachineApplicable,
+ );
+ }
+ BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span }=> {
+ let suggestion_span = vis_span.between(ident_span);
+ db.span_suggestion_verbose(
+ suggestion_span,
+ "convert it to a `use`",
+ if vis_span.is_empty() { "use " } else { " use " },
+ Applicability::MachineApplicable,
+ );
+ }
}
// Rewrap `db`, and pass control to the user.
decorate(db)
@@ -1101,11 +1129,9 @@ impl<'tcx> LateContext<'tcx> {
.maybe_typeck_results()
.filter(|typeck_results| typeck_results.hir_owner == id.owner)
.or_else(|| {
- if self.tcx.has_typeck_results(id.owner.to_def_id()) {
- Some(self.tcx.typeck(id.owner.def_id))
- } else {
- None
- }
+ self.tcx
+ .has_typeck_results(id.owner.to_def_id())
+ .then(|| self.tcx.typeck(id.owner.def_id))
})
.and_then(|typeck_results| typeck_results.type_dependent_def(id))
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index a45d8156c..ccf95992a 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
// `Deref` is being implemented for `t`
if let hir::ItemKind::Impl(impl_) = item.kind
&& let Some(trait_) = &impl_.of_trait
- && let t = cx.tcx.type_of(item.owner_id)
+ && let t = cx.tcx.type_of(item.owner_id).subst_identity()
&& let opt_did @ Some(did) = trait_.trait_def_id()
&& opt_did == cx.tcx.lang_items().deref_trait()
// `t` is `dyn t_principal`
diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
index 73bd41732..f1ba192f2 100644
--- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
+++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
@@ -4,7 +4,7 @@ use crate::{
LateContext, LateLintPass,
};
use rustc_hir as hir;
-use rustc_middle::ty::{visit::TypeVisitable, Ty};
+use rustc_middle::ty::{visit::TypeVisitableExt, Ty};
use rustc_span::{symbol::sym, Span};
declare_lint! {
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index f3ae26091..9af5284df 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,6 +1,6 @@
+use crate::fluent_generated as fluent;
use rustc_errors::{
- fluent, AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic,
- SubdiagnosticMessage,
+ AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic, SubdiagnosticMessage,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::lint::Level;
@@ -116,7 +116,7 @@ impl IntoDiagnostic<'_> for CheckNameUnknown {
let mut diag = handler.struct_err(fluent::lint_check_name_unknown);
diag.code(rustc_errors::error_code!(E0602));
if let Some(suggestion) = self.suggestion {
- diag.help(fluent::help);
+ diag.help(fluent::lint_help);
diag.set_arg("suggestion", suggestion);
}
diag.set_arg("lint_name", self.lint_name);
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 5219992ee..a3367ae4a 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -65,11 +65,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
} else {
ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), end_span: pat.span.between(arg.span), var }
} ;
- let question_mark = if suggest_question_mark(cx, adt, substs, expr.span) {
- Some(ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() })
- } else {
- None
- };
+ let question_mark = suggest_question_mark(cx, adt, substs, expr.span)
+ .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() });
let suggestion = ForLoopsOverFalliblesSuggestion {
var,
start_span: expr.span.with_hi(pat.span.lo()),
@@ -139,9 +136,10 @@ fn suggest_question_mark<'tcx>(
let ty = substs.type_at(0);
let infcx = cx.tcx.infer_ctxt().build();
+ let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
let cause = ObligationCause::new(
span,
- body_id.hir_id,
+ body_def_id,
rustc_infer::traits::ObligationCauseCode::MiscObligation,
);
let errors = rustc_trait_selection::traits::fully_solve_bound(
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 6cefaea2b..2fd0ef3cd 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -216,7 +216,7 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
}
// Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
- if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+ if let ty::Adt(adt, substs) = cx.tcx.type_of(did).subst_identity().kind() {
if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
{
// NOTE: This path is currently unreachable as `Ty<'tcx>` is
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index b2a265674..b42878a02 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -66,13 +66,12 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
self.context.last_node_with_lint_attrs = prev;
}
- fn with_param_env<F>(&mut self, id: hir::HirId, f: F)
+ fn with_param_env<F>(&mut self, id: hir::OwnerId, f: F)
where
F: FnOnce(&mut Self),
{
let old_param_env = self.context.param_env;
- self.context.param_env =
- self.context.tcx.param_env(self.context.tcx.hir().local_def_id(id));
+ self.context.param_env = self.context.tcx.param_env(id);
f(self);
self.context.param_env = old_param_env;
}
@@ -132,7 +131,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
let old_cached_typeck_results = self.context.cached_typeck_results.take();
let old_enclosing_body = self.context.enclosing_body.take();
self.with_lint_attrs(it.hir_id(), |cx| {
- cx.with_param_env(it.hir_id(), |cx| {
+ cx.with_param_env(it.owner_id, |cx| {
lint_callback!(cx, check_item, it);
hir_visit::walk_item(cx, it);
lint_callback!(cx, check_item_post, it);
@@ -145,7 +144,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
self.with_lint_attrs(it.hir_id(), |cx| {
- cx.with_param_env(it.hir_id(), |cx| {
+ cx.with_param_env(it.owner_id, |cx| {
lint_callback!(cx, check_foreign_item, it);
hir_visit::walk_foreign_item(cx, it);
});
@@ -180,7 +179,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
decl: &'tcx hir::FnDecl<'tcx>,
body_id: hir::BodyId,
span: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
// Wrap in typeck results here, not just in visit_nested_body,
// in order for `check_fn` to be able to use them.
@@ -268,7 +267,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
let generics = self.context.generics.take();
self.context.generics = Some(&trait_item.generics);
self.with_lint_attrs(trait_item.hir_id(), |cx| {
- cx.with_param_env(trait_item.hir_id(), |cx| {
+ cx.with_param_env(trait_item.owner_id, |cx| {
lint_callback!(cx, check_trait_item, trait_item);
hir_visit::walk_trait_item(cx, trait_item);
});
@@ -280,7 +279,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
let generics = self.context.generics.take();
self.context.generics = Some(&impl_item.generics);
self.with_lint_attrs(impl_item.hir_id(), |cx| {
- cx.with_param_env(impl_item.hir_id(), |cx| {
+ cx.with_param_env(impl_item.owner_id, |cx| {
lint_callback!(cx, check_impl_item, impl_item);
hir_visit::walk_impl_item(cx, impl_item);
lint_callback!(cx, check_impl_item_post, impl_item);
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index cca36913d..bc7488fab 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,13 +1,16 @@
-use crate::context::{CheckLintNameResult, LintStore};
-use crate::late::unerased_lint_store;
-use crate::lints::{
- DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint, RenamedOrRemovedLint,
- RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion,
+use crate::{
+ context::{CheckLintNameResult, LintStore},
+ fluent_generated as fluent,
+ late::unerased_lint_store,
+ lints::{
+ DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint,
+ RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion,
+ },
};
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{fluent, DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
+use rustc_errors::{DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
@@ -983,7 +986,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
fluent::lint_unknown_gated_lint,
|lint| {
lint.set_arg("name", lint_id.lint.name_lower());
- lint.note(fluent::note);
+ lint.note(fluent::lint_note);
add_feature_diagnostics(lint, &self.sess.parse_sess, feature);
lint
},
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index d6be4da03..35dc533e5 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -63,7 +63,9 @@ mod late;
mod let_underscore;
mod levels;
mod lints;
+mod map_unit_fn;
mod methods;
+mod multiple_supertrait_upcastable;
mod non_ascii_idents;
mod non_fmt_panic;
mod nonstandard_style;
@@ -79,8 +81,10 @@ mod unused;
pub use array_into_iter::ARRAY_INTO_ITER;
use rustc_ast as ast;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
+use rustc_macros::fluent_messages;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::{
@@ -97,7 +101,9 @@ use for_loops_over_fallibles::*;
use hidden_unicode_codepoints::*;
use internal::*;
use let_underscore::*;
+use map_unit_fn::*;
use methods::*;
+use multiple_supertrait_upcastable::*;
use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
use nonstandard_style::*;
@@ -120,6 +126,8 @@ pub use rustc_session::lint::Level::{self, *};
pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId};
pub use rustc_session::lint::{LintArray, LintPass};
+fluent_messages! { "../locales/en-US.ftl" }
+
pub fn provide(providers: &mut Providers) {
levels::provide(providers);
expect::provide(providers);
@@ -232,6 +240,8 @@ late_lint_methods!(
InvalidAtomicOrdering: InvalidAtomicOrdering,
NamedAsmLabels: NamedAsmLabels,
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
+ MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
+ MapUnitFn: MapUnitFn,
]
]
);
@@ -291,7 +301,8 @@ fn register_builtins(store: &mut LintStore) {
UNUSED_LABELS,
UNUSED_PARENS,
UNUSED_BRACES,
- REDUNDANT_SEMICOLONS
+ REDUNDANT_SEMICOLONS,
+ MAP_UNIT_FN
);
add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK);
@@ -321,7 +332,6 @@ fn register_builtins(store: &mut LintStore) {
store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
store.register_renamed("redundant_semicolon", "redundant_semicolons");
store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
- store.register_renamed("safe_packed_borrows", "unaligned_references");
store.register_renamed("disjoint_capture_migration", "rust_2021_incompatible_closure_captures");
store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns");
store.register_renamed("non_fmt_panic", "non_fmt_panics");
@@ -484,6 +494,16 @@ fn register_builtins(store: &mut LintStore) {
"converted into hard error, see issue #71800 \
<https://github.com/rust-lang/rust/issues/71800> for more information",
);
+ store.register_removed(
+ "safe_packed_borrows",
+ "converted into hard error, see issue #82523 \
+ <https://github.com/rust-lang/rust/issues/82523> for more information",
+ );
+ store.register_removed(
+ "unaligned_references",
+ "converted into hard error, see issue #82523 \
+ <https://github.com/rust-lang/rust/issues/82523> for more information",
+ );
}
fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 329ece28e..20ab0af58 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2,13 +2,16 @@
#![allow(rustc::diagnostic_outside_of_impl)]
use std::num::NonZeroU32;
+use crate::fluent_generated as fluent;
use rustc_errors::{
- fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage,
- DiagnosticStyledString, SuggestionStyle,
+ AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, DiagnosticStyledString,
+ SuggestionStyle,
};
use rustc_hir::def_id::DefId;
use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::{PolyExistentialTraitRef, Predicate, Ty, TyCtxt};
+use rustc_middle::ty::{
+ inhabitedness::InhabitedPredicate, PolyExistentialTraitRef, Predicate, Ty, TyCtxt,
+};
use rustc_session::parse::ParseSess;
use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
@@ -21,7 +24,7 @@ use crate::{
#[diag(lint_array_into_iter)]
pub struct ArrayIntoIterDiag<'a> {
pub target: &'a str,
- #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
+ #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
pub suggestion: Span,
#[subdiagnostic]
pub sub: Option<ArrayIntoIterDiagSub>,
@@ -29,12 +32,15 @@ pub struct ArrayIntoIterDiag<'a> {
#[derive(Subdiagnostic)]
pub enum ArrayIntoIterDiagSub {
- #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
+ #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
RemoveIntoIter {
#[primary_span]
span: Span,
},
- #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")]
+ #[multipart_suggestion(
+ lint_use_explicit_into_iter_suggestion,
+ applicability = "maybe-incorrect"
+ )]
UseExplicitIntoIter {
#[suggestion_part(code = "IntoIterator::into_iter(")]
start_span: Span,
@@ -161,13 +167,13 @@ pub struct BuiltinDeprecatedAttrLink<'a> {
#[derive(Subdiagnostic)]
pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> {
- #[suggestion(msg_suggestion, code = "", applicability = "machine-applicable")]
+ #[suggestion(lint_msg_suggestion, code = "", applicability = "machine-applicable")]
Msg {
#[primary_span]
suggestion: Span,
msg: &'a str,
},
- #[suggestion(default_suggestion, code = "", applicability = "machine-applicable")]
+ #[suggestion(lint_default_suggestion, code = "", applicability = "machine-applicable")]
Default {
#[primary_span]
suggestion: Span,
@@ -199,9 +205,9 @@ pub struct BuiltinUnusedDocComment<'a> {
#[derive(Subdiagnostic)]
pub enum BuiltinUnusedDocCommentSub {
- #[help(plain_help)]
+ #[help(lint_plain_help)]
PlainHelp,
- #[help(block_help)]
+ #[help(lint_block_help)]
BlockHelp,
}
@@ -240,7 +246,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
self,
diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
- diag.span_label(self.label, fluent::label);
+ diag.span_label(self.label, fluent::lint_label);
rustc_session::parse::add_feature_diagnostics(
diag,
&self.parse_sess,
@@ -335,7 +341,7 @@ impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
) -> rustc_errors::SubdiagnosticMessage,
{
diag.multipart_suggestion(
- fluent::suggestion,
+ fluent::lint_suggestion,
self.suggestions,
Applicability::MachineApplicable,
);
@@ -386,7 +392,7 @@ pub struct BuiltinExplicitOutlives {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion)]
+#[multipart_suggestion(lint_suggestion)]
pub struct BuiltinExplicitOutlivesSuggestion {
#[suggestion_part(code = "")]
pub spans: Vec<Span>,
@@ -405,11 +411,11 @@ pub struct BuiltinIncompleteFeatures {
}
#[derive(Subdiagnostic)]
-#[help(help)]
+#[help(lint_help)]
pub struct BuiltinIncompleteFeaturesHelp;
#[derive(Subdiagnostic)]
-#[note(note)]
+#[note(lint_note)]
pub struct BuiltinIncompleteFeaturesNote {
pub n: NonZeroU32,
}
@@ -419,6 +425,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> {
pub ty: Ty<'a>,
pub label: Span,
pub sub: BuiltinUnpermittedTypeInitSub,
+ pub tcx: TyCtxt<'a>,
}
impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
@@ -428,7 +435,13 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
diag.set_arg("ty", self.ty);
diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
- diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label_suggestion);
+ if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) {
+ // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited.
+ diag.span_label(
+ self.label,
+ fluent::lint_builtin_unpermitted_type_init_label_suggestion,
+ );
+ }
self.sub.add_to_diagnostic(diag);
diag
}
@@ -473,9 +486,9 @@ pub enum BuiltinClashingExtern<'a> {
SameName {
this: Symbol,
orig: Symbol,
- #[label(previous_decl_label)]
+ #[label(lint_previous_decl_label)]
previous_decl_label: Span,
- #[label(mismatch_label)]
+ #[label(lint_mismatch_label)]
mismatch_label: Span,
#[subdiagnostic]
sub: BuiltinClashingExternSub<'a>,
@@ -484,9 +497,9 @@ pub enum BuiltinClashingExtern<'a> {
DiffName {
this: Symbol,
orig: Symbol,
- #[label(previous_decl_label)]
+ #[label(lint_previous_decl_label)]
previous_decl_label: Span,
- #[label(mismatch_label)]
+ #[label(lint_mismatch_label)]
mismatch_label: Span,
#[subdiagnostic]
sub: BuiltinClashingExternSub<'a>,
@@ -562,7 +575,7 @@ pub struct SupertraitAsDerefTarget<'a> {
}
#[derive(Subdiagnostic)]
-#[label(label)]
+#[label(lint_label)]
pub struct SupertraitAsDerefTargetLabel {
#[primary_span]
pub label: Span,
@@ -595,7 +608,7 @@ pub struct Expectation {
}
#[derive(Subdiagnostic)]
-#[note(rationale)]
+#[note(lint_rationale)]
pub struct ExpectationNote {
pub rationale: Symbol,
}
@@ -616,13 +629,13 @@ pub struct ForLoopsOverFalliblesDiag<'a> {
#[derive(Subdiagnostic)]
pub enum ForLoopsOverFalliblesLoopSub<'a> {
- #[suggestion(remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
+ #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
RemoveNext {
#[primary_span]
suggestion: Span,
recv_snip: String,
},
- #[multipart_suggestion(use_while_let, applicability = "maybe-incorrect")]
+ #[multipart_suggestion(lint_use_while_let, applicability = "maybe-incorrect")]
UseWhileLet {
#[suggestion_part(code = "while let {var}(")]
start_span: Span,
@@ -633,14 +646,14 @@ pub enum ForLoopsOverFalliblesLoopSub<'a> {
}
#[derive(Subdiagnostic)]
-#[suggestion(use_question_mark, code = "?", applicability = "maybe-incorrect")]
+#[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")]
pub struct ForLoopsOverFalliblesQuestionMark {
#[primary_span]
pub suggestion: Span,
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
+#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
pub struct ForLoopsOverFalliblesSuggestion<'a> {
pub var: &'a str,
#[suggestion_part(code = "if let {var}(")]
@@ -699,13 +712,13 @@ impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
match self {
HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
diag.multipart_suggestion_with_style(
- fluent::suggestion_remove,
+ fluent::lint_suggestion_remove,
spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
Applicability::MachineApplicable,
SuggestionStyle::HideCodeAlways,
);
diag.multipart_suggestion(
- fluent::suggestion_escape,
+ fluent::lint_suggestion_escape,
spans
.into_iter()
.map(|(c, span)| {
@@ -728,13 +741,29 @@ impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
.collect::<Vec<String>>()
.join(", "),
);
- diag.note(fluent::suggestion_remove);
- diag.note(fluent::no_suggestion_note_escape);
+ diag.note(fluent::lint_suggestion_remove);
+ diag.note(fluent::lint_no_suggestion_note_escape);
}
}
}
}
+// map_unit_fn.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_map_unit_fn)]
+#[note]
+pub struct MappingToUnit {
+ #[label(lint_function_label)]
+ pub function_label: Span,
+ #[label(lint_argument_label)]
+ pub argument_label: Span,
+ #[label(lint_map_label)]
+ pub map_label: Span,
+ #[suggestion(style = "verbose", code = "{replace}", applicability = "maybe-incorrect")]
+ pub suggestion: Span,
+ pub replace: String,
+}
+
// internal.rs
#[derive(LintDiagnostic)]
#[diag(lint_default_hash_types)]
@@ -874,7 +903,7 @@ pub struct RenamedOrRemovedLint<'a> {
}
#[derive(Subdiagnostic)]
-#[suggestion(suggestion, code = "{replace}", applicability = "machine-applicable")]
+#[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
pub struct RenamedOrRemovedLintSuggestion<'a> {
#[primary_span]
pub suggestion: Span,
@@ -890,7 +919,7 @@ pub struct UnknownLint {
}
#[derive(Subdiagnostic)]
-#[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
+#[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
pub struct UnknownLintSuggestion {
#[primary_span]
pub suggestion: Span,
@@ -910,12 +939,19 @@ pub struct IgnoredUnlessCrateSpecified<'a> {
#[note]
#[help]
pub struct CStringPtr {
- #[label(as_ptr_label)]
+ #[label(lint_as_ptr_label)]
pub as_ptr: Span,
- #[label(unwrap_label)]
+ #[label(lint_unwrap_label)]
pub unwrap: Span,
}
+// multiple_supertrait_upcastable.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_multple_supertrait_upcastable)]
+pub struct MultipleSupertraitUpcastable {
+ pub ident: Ident,
+}
+
// non_ascii_idents.rs
#[derive(LintDiagnostic)]
#[diag(lint_identifier_non_ascii_char)]
@@ -936,7 +972,7 @@ pub struct ConfusableIdentifierPair {
#[derive(LintDiagnostic)]
#[diag(lint_mixed_script_confusables)]
-#[note(includes_note)]
+#[note(lint_includes_note)]
#[note]
pub struct MixedScriptConfusables {
pub set: String,
@@ -956,17 +992,17 @@ impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
diag.set_arg("count", self.count);
- diag.note(fluent::note);
+ diag.note(fluent::lint_note);
if let Some(span) = self.suggestion {
diag.span_suggestion(
span.shrink_to_hi(),
- fluent::add_args_suggestion,
+ fluent::lint_add_args_suggestion,
", ...",
Applicability::HasPlaceholders,
);
diag.span_suggestion(
span.shrink_to_lo(),
- fluent::add_fmt_suggestion,
+ fluent::lint_add_fmt_suggestion,
"\"{}\", ",
Applicability::MachineApplicable,
);
@@ -1000,12 +1036,12 @@ pub struct NonCamelCaseType<'a> {
#[derive(Subdiagnostic)]
pub enum NonCamelCaseTypeSub {
- #[label(label)]
+ #[label(lint_label)]
Label {
#[primary_span]
span: Span,
},
- #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
+ #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
Suggestion {
#[primary_span]
span: Span,
@@ -1041,15 +1077,15 @@ impl AddToDiagnostic for NonSnakeCaseDiagSub {
{
match self {
NonSnakeCaseDiagSub::Label { span } => {
- diag.span_label(span, fluent::label);
+ diag.span_label(span, fluent::lint_label);
}
NonSnakeCaseDiagSub::Help => {
- diag.help(fluent::help);
+ diag.help(fluent::lint_help);
}
NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
diag.span_suggestion(
span,
- fluent::convert_suggestion,
+ fluent::lint_convert_suggestion,
suggestion,
Applicability::MaybeIncorrect,
);
@@ -1057,16 +1093,16 @@ impl AddToDiagnostic for NonSnakeCaseDiagSub {
NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
diag.span_suggestion(
span,
- fluent::rename_or_convert_suggestion,
+ fluent::lint_rename_or_convert_suggestion,
suggestion,
Applicability::MaybeIncorrect,
);
}
NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
- diag.note(fluent::cannot_convert_note);
+ diag.note(fluent::lint_cannot_convert_note);
diag.span_suggestion(
span,
- fluent::rename_suggestion,
+ fluent::lint_rename_suggestion,
"",
Applicability::MaybeIncorrect,
);
@@ -1086,12 +1122,12 @@ pub struct NonUpperCaseGlobal<'a> {
#[derive(Subdiagnostic)]
pub enum NonUpperCaseGlobalSub {
- #[label(label)]
+ #[label(lint_label)]
Label {
#[primary_span]
span: Span,
},
- #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
+ #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
Suggestion {
#[primary_span]
span: Span,
@@ -1209,11 +1245,11 @@ impl AddToDiagnostic for OverflowingBinHexSign {
{
match self {
OverflowingBinHexSign::Positive => {
- diag.note(fluent::positive_note);
+ diag.note(fluent::lint_positive_note);
}
OverflowingBinHexSign::Negative => {
- diag.note(fluent::negative_note);
- diag.note(fluent::negative_becomes_note);
+ diag.note(fluent::lint_negative_note);
+ diag.note(fluent::lint_negative_becomes_note);
}
}
}
@@ -1222,7 +1258,7 @@ impl AddToDiagnostic for OverflowingBinHexSign {
#[derive(Subdiagnostic)]
pub enum OverflowingBinHexSub<'a> {
#[suggestion(
- suggestion,
+ lint_suggestion,
code = "{sans_suffix}{suggestion_ty}",
applicability = "machine-applicable"
)]
@@ -1232,7 +1268,7 @@ pub enum OverflowingBinHexSub<'a> {
suggestion_ty: &'a str,
sans_suffix: &'a str,
},
- #[help(help)]
+ #[help(lint_help)]
Help { suggestion_ty: &'a str },
}
@@ -1249,7 +1285,7 @@ pub struct OverflowingInt<'a> {
}
#[derive(Subdiagnostic)]
-#[help(help)]
+#[help(lint_help)]
pub struct OverflowingIntHelp<'a> {
pub suggestion_ty: &'a str,
}
@@ -1301,13 +1337,13 @@ impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
diag.set_arg("ty", self.ty);
diag.set_arg("desc", self.desc);
- diag.span_label(self.label, fluent::label);
+ diag.span_label(self.label, fluent::lint_label);
if let Some(help) = self.help {
diag.help(help);
}
diag.note(self.note);
if let Some(note) = self.span_note {
- diag.span_note(note, fluent::note);
+ diag.span_note(note, fluent::lint_note);
}
diag
}
@@ -1394,6 +1430,21 @@ pub struct UnusedDef<'a, 'b> {
pub cx: &'a LateContext<'b>,
pub def_id: DefId,
pub note: Option<Symbol>,
+ pub suggestion: Option<UnusedDefSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnusedDefSuggestion {
+ #[suggestion(
+ lint_suggestion,
+ style = "verbose",
+ code = "let _ = ",
+ applicability = "machine-applicable"
+ )]
+ Default {
+ #[primary_span]
+ span: Span,
+ },
}
// Needed because of def_path_str
@@ -1409,6 +1460,9 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
if let Some(note) = self.note {
diag.note(note.as_str());
}
+ if let Some(sugg) = self.suggestion {
+ diag.subdiagnostic(sugg);
+ }
diag
}
@@ -1426,13 +1480,13 @@ pub struct PathStatementDrop {
#[derive(Subdiagnostic)]
pub enum PathStatementDropSub {
- #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
+ #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
Suggestion {
#[primary_span]
span: Span,
snippet: String,
},
- #[help(help)]
+ #[help(lint_help)]
Help {
#[primary_span]
span: Span,
@@ -1453,7 +1507,7 @@ pub struct UnusedDelim<'a> {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
pub struct UnusedDelimSuggestion {
#[suggestion_part(code = "{start_replace}")]
pub start_span: Span,
diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs
new file mode 100644
index 000000000..62e8b4fe9
--- /dev/null
+++ b/compiler/rustc_lint/src/map_unit_fn.rs
@@ -0,0 +1,120 @@
+use crate::lints::MappingToUnit;
+use crate::{LateContext, LateLintPass, LintContext};
+
+use rustc_hir::{Expr, ExprKind, HirId, Stmt, StmtKind};
+use rustc_middle::{
+ query::Key,
+ ty::{self, Ty},
+};
+
+declare_lint! {
+ /// The `map_unit_fn` lint checks for `Iterator::map` receive
+ /// a callable that returns `()`.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// fn foo(items: &mut Vec<u8>) {
+ /// items.sort();
+ /// }
+ ///
+ /// fn main() {
+ /// let mut x: Vec<Vec<u8>> = vec![
+ /// vec![0, 2, 1],
+ /// vec![5, 4, 3],
+ /// ];
+ /// x.iter_mut().map(foo);
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Mapping to `()` is almost always a mistake.
+ pub MAP_UNIT_FN,
+ Warn,
+ "`Iterator::map` call that discard the iterator's values"
+}
+
+declare_lint_pass!(MapUnitFn => [MAP_UNIT_FN]);
+
+impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
+ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'_>) {
+ if stmt.span.from_expansion() {
+ return;
+ }
+
+ if let StmtKind::Semi(expr) = stmt.kind {
+ if let ExprKind::MethodCall(path, receiver, args, span) = expr.kind {
+ if path.ident.name.as_str() == "map" {
+ if receiver.span.from_expansion()
+ || args.iter().any(|e| e.span.from_expansion())
+ || !is_impl_slice(cx, receiver)
+ || !is_diagnostic_name(cx, expr.hir_id, "IteratorMap")
+ {
+ return;
+ }
+ let arg_ty = cx.typeck_results().expr_ty(&args[0]);
+ if let ty::FnDef(id, _) = arg_ty.kind() {
+ let fn_ty = cx.tcx.fn_sig(id).skip_binder();
+ let ret_ty = fn_ty.output().skip_binder();
+ if is_unit_type(ret_ty) {
+ cx.emit_spanned_lint(
+ MAP_UNIT_FN,
+ span,
+ MappingToUnit {
+ function_label: cx.tcx.span_of_impl(*id).unwrap(),
+ argument_label: args[0].span,
+ map_label: arg_ty.default_span(cx.tcx),
+ suggestion: path.ident.span,
+ replace: "for_each".to_string(),
+ },
+ )
+ }
+ } else if let ty::Closure(id, subs) = arg_ty.kind() {
+ let cl_ty = subs.as_closure().sig();
+ let ret_ty = cl_ty.output().skip_binder();
+ if is_unit_type(ret_ty) {
+ cx.emit_spanned_lint(
+ MAP_UNIT_FN,
+ span,
+ MappingToUnit {
+ function_label: cx.tcx.span_of_impl(*id).unwrap(),
+ argument_label: args[0].span,
+ map_label: arg_ty.default_span(cx.tcx),
+ suggestion: path.ident.span,
+ replace: "for_each".to_string(),
+ },
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+fn is_impl_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
+ if let Some(impl_id) = cx.tcx.impl_of_method(method_id) {
+ return cx.tcx.type_of(impl_id).skip_binder().is_slice();
+ }
+ }
+ false
+}
+
+fn is_unit_type(ty: Ty<'_>) -> bool {
+ ty.is_unit() || ty.is_never()
+}
+
+fn is_diagnostic_name(cx: &LateContext<'_>, id: HirId, name: &str) -> bool {
+ if let Some(def_id) = cx.typeck_results().type_dependent_def_id(id) {
+ if let Some(item) = cx.tcx.get_diagnostic_name(def_id) {
+ if item.as_str() == name {
+ return true;
+ }
+ }
+ }
+ false
+}
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
new file mode 100644
index 000000000..c2ed0e19f
--- /dev/null
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -0,0 +1,60 @@
+use crate::{LateContext, LateLintPass, LintContext};
+
+use rustc_hir as hir;
+use rustc_span::sym;
+
+declare_lint! {
+ /// The `multiple_supertrait_upcastable` lint detects when an object-safe trait has multiple
+ /// supertraits.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// trait A {}
+ /// trait B {}
+ ///
+ /// #[warn(multiple_supertrait_upcastable)]
+ /// trait C: A + B {}
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// To support upcasting with multiple supertraits, we need to store multiple vtables and this
+ /// can result in extra space overhead, even if no code actually uses upcasting.
+ /// This lint allows users to identify when such scenarios occur and to decide whether the
+ /// additional overhead is justified.
+ pub MULTIPLE_SUPERTRAIT_UPCASTABLE,
+ Allow,
+ "detect when an object-safe trait has multiple supertraits",
+ @feature_gate = sym::multiple_supertrait_upcastable;
+}
+
+declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTABLE]);
+
+impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+ let def_id = item.owner_id.to_def_id();
+ // NOTE(nbdd0121): use `object_safety_violations` instead of `check_is_object_safe` because
+ // the latter will report `where_clause_object_safety` lint.
+ if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
+ && cx.tcx.object_safety_violations(def_id).is_empty()
+ {
+ let direct_super_traits_iter = cx.tcx
+ .super_predicates_of(def_id)
+ .predicates
+ .into_iter()
+ .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred());
+ if direct_super_traits_iter.count() > 1 {
+ cx.emit_spanned_lint(
+ MULTIPLE_SUPERTRAIT_UPCASTABLE,
+ cx.tcx.def_span(def_id),
+ crate::lints::MultipleSupertraitUpcastable {
+ ident: item.ident
+ },
+ );
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 4a02c6cce..5bb1abfd2 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -1,7 +1,7 @@
use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
-use crate::{LateContext, LateLintPass, LintContext};
+use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
-use rustc_errors::{fluent, Applicability};
+use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::lint::in_external_macro;
@@ -122,18 +122,18 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
#[allow(rustc::diagnostic_outside_of_impl)]
cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| {
lint.set_arg("name", symbol);
- lint.note(fluent::note);
- lint.note(fluent::more_info_note);
+ lint.note(fluent::lint_note);
+ lint.note(fluent::lint_more_info_note);
if !is_arg_inside_call(arg_span, span) {
// No clue where this argument is coming from.
return lint;
}
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
// A case of `panic!(format!(..))`.
- lint.note(fluent::supports_fmt_note);
+ lint.note(fluent::lint_supports_fmt_note);
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
lint.multipart_suggestion(
- fluent::supports_fmt_suggestion,
+ fluent::lint_supports_fmt_suggestion,
vec![
(arg_span.until(open.shrink_to_hi()), "".into()),
(close.until(arg_span.shrink_to_hi()), "".into()),
@@ -146,7 +146,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
// If this is a &str or String, we can confidently give the `"{}", ` suggestion.
let is_str = matches!(
ty.kind(),
- ty::Ref(_, r, _) if *r.kind() == ty::Str,
+ ty::Ref(_, r, _) if r.is_str(),
) || matches!(
ty.ty_adt_def(),
Some(ty_def) if Some(ty_def.did()) == cx.tcx.lang_items().string(),
@@ -179,7 +179,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
if suggest_display {
lint.span_suggestion_verbose(
arg_span.shrink_to_lo(),
- fluent::display_suggestion,
+ fluent::lint_display_suggestion,
"\"{}\", ",
fmt_applicability,
);
@@ -187,7 +187,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
lint.set_arg("ty", ty);
lint.span_suggestion_verbose(
arg_span.shrink_to_lo(),
- fluent::debug_suggestion,
+ fluent::lint_debug_suggestion,
"\"{:?}\", ",
fmt_applicability,
);
@@ -197,7 +197,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
if let Some((open, close, del)) = find_delimiters(cx, span) {
lint.set_arg("already_suggested", suggest_display || suggest_debug);
lint.multipart_suggestion(
- fluent::panic_suggestion,
+ fluent::lint_panic_suggestion,
if del == '(' {
vec![(span.until(open), "std::panic::panic_any".into())]
} else {
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 74d234fab..71e2e66bd 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -10,8 +10,9 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{GenericParamKind, PatKind};
use rustc_middle::ty;
-use rustc_span::symbol::sym;
-use rustc_span::{symbol::Ident, BytePos, Span};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{BytePos, Span};
use rustc_target::spec::abi::Abi;
#[derive(PartialEq)]
@@ -21,9 +22,8 @@ pub enum MethodLateContext {
PlainImpl,
}
-pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext {
- let def_id = cx.tcx.hir().local_def_id(id);
- let item = cx.tcx.associated_item(def_id);
+pub fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext {
+ let item = cx.tcx.associated_item(id);
match item.container {
ty::TraitContainer => MethodLateContext::TraitAutoImpl,
ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
@@ -379,13 +379,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
_: &hir::FnDecl<'_>,
_: &hir::Body<'_>,
_: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
- let attrs = cx.tcx.hir().attrs(id);
match &fk {
FnKind::Method(ident, sig, ..) => match method_context(cx, id) {
MethodLateContext::PlainImpl => {
- if sig.header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle)
+ if sig.header.abi != Abi::Rust
+ && cx.tcx.has_attr(id.to_def_id(), sym::no_mangle)
{
return;
}
@@ -398,7 +398,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
},
FnKind::ItemFn(ident, _, header) => {
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
- if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
+ if header.abi != Abi::Rust && cx.tcx.has_attr(id.to_def_id(), sym::no_mangle) {
return;
}
self.check_snake_case(cx, "function", ident);
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 42442cfb1..883a56cb3 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -149,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
struct OpaqueHiddenInferredBoundLint<'tcx> {
ty: Ty<'tcx>,
proj_ty: Ty<'tcx>,
- #[label(specifically)]
+ #[label(lint_specifically)]
assoc_pred_span: Span,
#[subdiagnostic]
add_bound: Option<AddBound<'tcx>>,
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 392e13f2f..2bb2a3aab 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -50,7 +50,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
}
Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
- if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+ if let ty::Adt(adt, substs) = cx.tcx.type_of(did).subst_identity().kind() {
if cx.tcx.has_attr(adt.did(), sym::rustc_pass_by_value) {
return Some(cx.tcx.def_path_str_with_substs(adt.did(), substs));
}
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 0bf01c4e5..16964565b 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -4,6 +4,7 @@ use rustc_ast as ast;
use rustc_hir as hir;
use rustc_session::lint::builtin::HardwiredLints;
use rustc_session::lint::LintPass;
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::Ident;
use rustc_span::Span;
@@ -36,7 +37,7 @@ macro_rules! late_lint_methods {
b: &'tcx hir::FnDecl<'tcx>,
c: &'tcx hir::Body<'tcx>,
d: Span,
- e: hir::HirId);
+ e: LocalDefId);
fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index be47a3e23..85958c417 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,19 +1,25 @@
-use crate::lints::{
- AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
- InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
- OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
- RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag,
+use crate::{
+ fluent_generated as fluent,
+ lints::{
+ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
+ InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
+ OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
+ OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag,
+ },
};
use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{fluent, DiagnosticMessage};
+use rustc_errors::DiagnosticMessage;
use rustc_hir as hir;
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{
+ self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
@@ -650,7 +656,7 @@ pub fn transparent_newtype_field<'a, 'tcx>(
) -> Option<&'a ty::FieldDef> {
let param_env = tcx.param_env(variant.def_id);
variant.fields.iter().find(|field| {
- let field_ty = tcx.type_of(field.did);
+ let field_ty = tcx.type_of(field.did).subst_identity();
let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
!is_zst
})
@@ -1107,6 +1113,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Placeholder(..)
| ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
}
@@ -1142,7 +1149,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
struct ProhibitOpaqueTypes;
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueTypes {
type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -1223,9 +1230,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
- fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl<'_>) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
- let sig = self.cx.tcx.fn_sig(def_id);
+ fn check_foreign_fn(&mut self, def_id: LocalDefId, decl: &hir::FnDecl<'_>) {
+ let sig = self.cx.tcx.fn_sig(def_id).subst_identity();
let sig = self.cx.tcx.erase_late_bound_regions(sig);
for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) {
@@ -1238,9 +1244,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
- fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
- let ty = self.cx.tcx.type_of(def_id);
+ fn check_foreign_static(&mut self, id: hir::OwnerId, span: Span) {
+ let ty = self.cx.tcx.type_of(id).subst_identity();
self.check_type_for_ffi_and_report_errors(span, ty, true, false);
}
@@ -1260,10 +1265,10 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
if !vis.is_internal_abi(abi) {
match it.kind {
hir::ForeignItemKind::Fn(ref decl, _, _) => {
- vis.check_foreign_fn(it.hir_id(), decl);
+ vis.check_foreign_fn(it.owner_id.def_id, decl);
}
hir::ForeignItemKind::Static(ref ty, _) => {
- vis.check_foreign_static(it.hir_id(), ty.span);
+ vis.check_foreign_static(it.owner_id, ty.span);
}
hir::ForeignItemKind::Type => (),
}
@@ -1279,7 +1284,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
decl: &'tcx hir::FnDecl<'_>,
_: &'tcx hir::Body<'_>,
_: Span,
- hir_id: hir::HirId,
+ id: LocalDefId,
) {
use hir::intravisit::FnKind;
@@ -1291,7 +1296,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Definition };
if !vis.is_internal_abi(abi) {
- vis.check_foreign_fn(hir_id, decl);
+ vis.check_foreign_fn(id, decl);
}
}
}
@@ -1301,7 +1306,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind {
- let t = cx.tcx.type_of(it.owner_id);
+ let t = cx.tcx.type_of(it.owner_id).subst_identity();
let ty = cx.tcx.erase_regions(t);
let Ok(layout) = cx.layout_of(ty) else { return };
let Variants::Multiple {
@@ -1421,7 +1426,7 @@ impl InvalidAtomicOrdering {
&& recognized_names.contains(&method_path.ident.name)
&& let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& let Some(impl_did) = cx.tcx.impl_of_method(m_def_id)
- && let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def()
+ && let Some(adt) = cx.tcx.type_of(impl_did).subst_identity().ty_adt_def()
// skip extension traits, only lint functions from the standard library
&& cx.tcx.trait_id_of_impl(impl_did).is_none()
&& let parent = cx.tcx.parent(adt.did())
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 4c9b3df2d..3a92f5806 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1,7 +1,7 @@
use crate::lints::{
PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
- UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion,
- UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
+ UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim,
+ UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
};
use crate::Lint;
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@@ -309,7 +309,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
None
}
}
- ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) {
+ ty::Array(ty, len) => match len.try_eval_target_usize(cx.tcx, cx.param_env) {
// If the array is empty we don't lint, to avoid false positives
Some(0) | None => None,
// If the array is definitely non-empty, we can do `#[must_use]` checking.
@@ -418,6 +418,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
);
}
MustUsePath::Def(span, def_id, reason) => {
+ let suggestion = if matches!(
+ cx.tcx.get_diagnostic_name(*def_id),
+ Some(sym::add)
+ | Some(sym::sub)
+ | Some(sym::mul)
+ | Some(sym::div)
+ | Some(sym::rem)
+ | Some(sym::neg),
+ ) {
+ Some(UnusedDefSuggestion::Default { span: span.shrink_to_lo() })
+ } else {
+ None
+ };
cx.emit_spanned_lint(
UNUSED_MUST_USE,
*span,
@@ -427,6 +440,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx,
def_id: *def_id,
note: *reason,
+ suggestion,
},
);
}
@@ -495,6 +509,7 @@ enum UnusedDelimsCtx {
ArrayLenExpr,
AnonConst,
MatchArmExpr,
+ IndexExpr,
}
impl From<UnusedDelimsCtx> for &'static str {
@@ -514,6 +529,7 @@ impl From<UnusedDelimsCtx> for &'static str {
UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
UnusedDelimsCtx::MatchArmExpr => "match arm expression",
+ UnusedDelimsCtx::IndexExpr => "index expression",
}
}
}
@@ -661,6 +677,10 @@ trait UnusedDelimLint {
keep_space: (bool, bool),
) {
let primary_span = if let Some((lo, hi)) = spans {
+ if hi.is_empty() {
+ // do not point at delims that do not exist
+ return;
+ }
MultiSpan::from(vec![lo, hi])
} else {
MultiSpan::from(value_span)
@@ -733,6 +753,8 @@ trait UnusedDelimLint {
(value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
}
+ Index(_, ref value) => (value, UnusedDelimsCtx::IndexExpr, false, None, None),
+
Assign(_, ref value, _) | AssignOp(.., ref value) => {
(value, UnusedDelimsCtx::AssignedValue, false, None, None)
}