diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
commit | 631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch) | |
tree | a1b87c8f8cad01cf18f7c5f57a08f102771ed303 /compiler/rustc_lint | |
parent | Adding debian version 1.69.0+dfsg1-1. (diff) | |
download | rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip |
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_lint')
-rw-r--r-- | compiler/rustc_lint/messages.ftl (renamed from compiler/rustc_lint/locales/en-US.ftl) | 8 | ||||
-rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 66 | ||||
-rw-r--r-- | compiler/rustc_lint/src/context.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_lint/src/early.rs | 13 | ||||
-rw-r--r-- | compiler/rustc_lint/src/for_loops_over_fallibles.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_lint/src/internal.rs | 36 | ||||
-rw-r--r-- | compiler/rustc_lint/src/let_underscore.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_lint/src/levels.rs | 20 | ||||
-rw-r--r-- | compiler/rustc_lint/src/lib.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_lint/src/lints.rs | 68 | ||||
-rw-r--r-- | compiler/rustc_lint/src/map_unit_fn.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_lint/src/methods.rs | 49 | ||||
-rw-r--r-- | compiler/rustc_lint/src/non_ascii_idents.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_lint/src/nonstandard_style.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs | 21 | ||||
-rw-r--r-- | compiler/rustc_lint/src/types.rs | 42 | ||||
-rw-r--r-- | compiler/rustc_lint/src/unused.rs | 87 |
17 files changed, 256 insertions, 201 deletions
diff --git a/compiler/rustc_lint/locales/en-US.ftl b/compiler/rustc_lint/messages.ftl index 68e62c978..db15b176d 100644 --- a/compiler/rustc_lint/locales/en-US.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -91,7 +91,7 @@ lint_ty_qualified = usage of qualified `ty::{$ty}` 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 = \"...\")]` +lint_non_existent_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 = @@ -107,7 +107,7 @@ lint_cstring_ptr = getting the inner pointer of a temporary `CString` .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_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits lint_identifier_non_ascii_char = identifier contains non-ASCII characters @@ -197,7 +197,9 @@ 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_range_use_inclusive_range = 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}` diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5b2100b5d..6b387df78 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -58,7 +58,6 @@ 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, Node, PatKind, PredicateOrigin}; -use rustc_index::vec::Idx; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -69,7 +68,7 @@ use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, InnerSpan, Span}; -use rustc_target::abi::{Abi, VariantIdx}; +use rustc_target::abi::{Abi, FIRST_VARIANT}; use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt}; use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy}; @@ -358,29 +357,29 @@ impl EarlyLintPass for UnsafeCode { } ast::ItemKind::Fn(..) => { - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleFn); } - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameFn); } - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::link_section) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::link_section) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionFn); } } ast::ItemKind::Static(..) => { - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleStatic); } - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameStatic); } - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::link_section) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::link_section) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionStatic); } } @@ -391,10 +390,10 @@ impl EarlyLintPass for UnsafeCode { fn check_impl_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { if let ast::AssocItemKind::Fn(..) = it.kind { - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleMethod); } - if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { + if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameMethod); } } @@ -1123,12 +1122,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { }; match it.kind { hir::ItemKind::Fn(.., ref generics, _) => { - if let Some(no_mangle_attr) = cx.sess().find_by_name(attrs, sym::no_mangle) { + if let Some(no_mangle_attr) = attr::find_by_name(attrs, sym::no_mangle) { check_no_mangle_on_generic_fn(no_mangle_attr, None, generics, it.span); } } hir::ItemKind::Const(..) => { - if cx.sess().contains_name(attrs, sym::no_mangle) { + if attr::contains_name(attrs, sym::no_mangle) { // account for "pub const" (#45562) let start = cx .tcx @@ -1152,9 +1151,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => { for it in *items { if let hir::AssocItemKind::Fn { .. } = it.kind { - if let Some(no_mangle_attr) = cx - .sess() - .find_by_name(cx.tcx.hir().attrs(it.id.hir_id()), sym::no_mangle) + if let Some(no_mangle_attr) = + attr::find_by_name(cx.tcx.hir().attrs(it.id.hir_id()), sym::no_mangle) { check_no_mangle_on_generic_fn( no_mangle_attr, @@ -1306,7 +1304,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller { if fn_kind.asyncness() == IsAsync::Async && !cx.tcx.features().closure_track_caller // Now, check if the function has the `#[track_caller]` attribute - && let Some(attr) = cx.tcx.get_attr(def_id.to_def_id(), sym::track_caller) + && let Some(attr) = cx.tcx.get_attr(def_id, sym::track_caller) { cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller { label: span, @@ -1601,7 +1599,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { // Ignore projections, as they can only be global // if the trait bound is global Clause(Clause::Projection(..)) | - AliasEq(..) | + AliasRelate(..) | // Ignore bounds that a user can't type WellFormed(..) | ObjectSafe(..) | @@ -1836,7 +1834,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { } let attrs = cx.tcx.hir().attrs(it.hir_id()); - if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) { + if let Some(attr) = attr::find_by_name(attrs, sym::rustc_test_marker) { cx.emit_spanned_lint(UNNAMEABLE_TEST_ITEMS, attr.span, BuiltinUnnameableTestItems); } } @@ -1949,7 +1947,7 @@ impl KeywordIdents { }; // Don't lint `r#foo`. - if cx.sess().parse_sess.raw_identifier_spans.borrow().contains(&ident.span) { + if cx.sess().parse_sess.raw_identifier_spans.contains(ident.span) { return; } @@ -2748,10 +2746,7 @@ impl ClashingExternDeclarations { // information, we could have codegen_fn_attrs also give span information back for // where the attribute was defined. However, until this is found to be a // bottleneck, this does just fine. - ( - overridden_link_name, - tcx.get_attr(fi.owner_id.to_def_id(), sym::link_name).unwrap().span, - ) + (overridden_link_name, tcx.get_attr(fi.owner_id, sym::link_name).unwrap().span) }) { SymbolName::Link(overridden_link_name, overridden_link_name_span) @@ -2781,8 +2776,7 @@ impl ClashingExternDeclarations { // Given a transparent newtype, reach through and grab the inner // type unless the newtype makes the type non-null. - let non_transparent_ty = |ty: Ty<'tcx>| -> Ty<'tcx> { - let mut ty = ty; + let non_transparent_ty = |mut ty: Ty<'tcx>| -> Ty<'tcx> { loop { if let ty::Adt(def, substs) = *ty.kind() { let is_transparent = def.repr().transparent(); @@ -2792,14 +2786,14 @@ impl ClashingExternDeclarations { ty, is_transparent, is_non_null ); if is_transparent && !is_non_null { - debug_assert!(def.variants().len() == 1); - let v = &def.variant(VariantIdx::new(0)); - ty = transparent_newtype_field(tcx, v) - .expect( - "single-variant transparent structure with zero-sized field", - ) - .ty(tcx, substs); - continue; + debug_assert_eq!(def.variants().len(), 1); + let v = &def.variant(FIRST_VARIANT); + // continue with `ty`'s non-ZST field, + // otherwise `ty` is a ZST and we can return + if let Some(field) = transparent_newtype_field(tcx, v) { + ty = field.ty(tcx, substs); + continue; + } } } debug!("non_transparent_ty -> {:?}", ty); @@ -2813,10 +2807,8 @@ impl ClashingExternDeclarations { if !seen_types.insert((a, b)) { // We've encountered a cycle. There's no point going any further -- the types are // structurally the same. - return true; - } - let tcx = cx.tcx; - if a == b { + true + } else if a == b { // All nominally-same types are structurally same, too. true } else { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index f5a711315..626c09fea 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -910,6 +910,10 @@ pub trait LintContext: Sized { Applicability::MachineApplicable, ); } + BuiltinLintDiagnostics::AmbiguousGlobReexports { name, namespace, first_reexport_span, duplicate_reexport_span } => { + db.span_label(first_reexport_span, format!("the name `{}` in the {} namespace is first re-exported here", name, namespace)); + db.span_label(duplicate_reexport_span, format!("but the name `{}` in the {} namespace is also re-exported here", name, namespace)); + } } // Rewrap `db`, and pass control to the user. decorate(db) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 337a19dd0..65607d718 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -224,8 +224,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> ast::ExprKind::Closure(box ast::Closure { asyncness: ast::Async::Yes { closure_id, .. }, .. - }) - | ast::ExprKind::Async(_, closure_id, ..) => self.check_id(closure_id), + }) => self.check_id(closure_id), _ => {} } } @@ -341,7 +340,7 @@ pub trait EarlyCheckNode<'a>: Copy { 'a: 'b; } -impl<'a> EarlyCheckNode<'a> for &'a ast::Crate { +impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) { fn id(self) -> ast::NodeId { ast::CRATE_NODE_ID } @@ -349,15 +348,15 @@ impl<'a> EarlyCheckNode<'a> for &'a ast::Crate { where 'a: 'b, { - &self.attrs + &self.1 } fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) where 'a: 'b, { - lint_callback!(cx, check_crate, self); - ast_visit::walk_crate(cx, self); - lint_callback!(cx, check_crate_post, self); + lint_callback!(cx, check_crate, self.0); + ast_visit::walk_crate(cx, self.0); + lint_callback!(cx, check_crate_post, self.0); } } diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index a3367ae4a..7b58bf03b 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -11,6 +11,7 @@ use rustc_hir as hir; use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause}; use rustc_middle::ty::{self, List}; use rustc_span::{sym, Span}; +use rustc_trait_selection::traits::ObligationCtxt; declare_lint! { /// The `for_loops_over_fallibles` lint checks for `for` loops over `Option` or `Result` values. @@ -136,20 +137,22 @@ fn suggest_question_mark<'tcx>( let ty = substs.type_at(0); let infcx = cx.tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); + let body_def_id = cx.tcx.hir().body_owner_def_id(body_id); let cause = ObligationCause::new( span, body_def_id, rustc_infer::traits::ObligationCauseCode::MiscObligation, ); - let errors = rustc_trait_selection::traits::fully_solve_bound( - &infcx, + + ocx.register_bound( cause, - ty::ParamEnv::empty(), + cx.param_env, // Erase any region vids from the type, which may not be resolved infcx.tcx.erase_regions(ty), into_iterator_did, ); - errors.is_empty() + ocx.select_all_or_error().is_empty() } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 2fd0ef3cd..4ac589c2e 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -2,7 +2,7 @@ //! Clippy. use crate::lints::{ - BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistantDocKeyword, + BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -17,6 +17,11 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; declare_tool_lint! { + /// The `default_hash_type` lint detects use of [`std::collections::HashMap`]/[`std::collections::HashSet`], + /// suggesting the use of `FxHashMap`/`FxHashSet`. + /// + /// This can help as `FxHasher` can perform better than the default hasher. DOS protection is not + /// required as input is assumed to be trusted. pub rustc::DEFAULT_HASH_TYPES, Allow, "forbid HashMap and HashSet and suggest the FxHash* variants", @@ -67,6 +72,12 @@ fn typeck_results_of_method_fn<'tcx>( } declare_tool_lint! { + /// The `potential_query_instability` lint detects use of methods which can lead to + /// potential query instability, such as iterating over a `HashMap`. + /// + /// Due to the [incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html) model, + /// queries must return deterministic, stable results. `HashMap` iteration order can change between compilations, + /// and will introduce instability if query results expose the order. pub rustc::POTENTIAL_QUERY_INSTABILITY, Allow, "require explicit opt-in when using potentially unstable methods or functions", @@ -92,6 +103,8 @@ impl LateLintPass<'_> for QueryStability { } declare_tool_lint! { + /// The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`, + /// where `ty::<kind>` would suffice. pub rustc::USAGE_OF_TY_TYKIND, Allow, "usage of `ty::TyKind` outside of the `ty::sty` module", @@ -99,6 +112,8 @@ declare_tool_lint! { } declare_tool_lint! { + /// The `usage_of_qualified_ty` lint detects usages of `ty::TyKind`, + /// where `Ty` should be used instead. pub rustc::USAGE_OF_QUALIFIED_TY, Allow, "using `ty::{Ty,TyCtxt}` instead of importing it", @@ -254,6 +269,8 @@ fn gen_args(segment: &PathSegment<'_>) -> String { } declare_tool_lint! { + /// The `lint_pass_impl_without_macro` detects manual implementations of a lint + /// pass, without using [`declare_lint_pass`] or [`impl_lint_pass`]. pub rustc::LINT_PASS_IMPL_WITHOUT_MACRO, Allow, "`impl LintPass` without the `declare_lint_pass!` or `impl_lint_pass!` macros" @@ -285,6 +302,8 @@ impl EarlyLintPass for LintPassImpl { } declare_tool_lint! { + /// The `existing_doc_keyword` lint detects use `#[doc()]` keywords + /// that don't exist, e.g. `#[doc(keyword = "..")]`. pub rustc::EXISTING_DOC_KEYWORD, Allow, "Check that documented keywords in std and core actually exist", @@ -315,7 +334,7 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { cx.emit_spanned_lint( EXISTING_DOC_KEYWORD, attr.span, - NonExistantDocKeyword { keyword }, + NonExistentDocKeyword { keyword }, ); } } @@ -325,6 +344,10 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { } declare_tool_lint! { + /// The `untranslatable_diagnostic` lint detects diagnostics created + /// without using translatable Fluent strings. + /// + /// More details on translatable diagnostics can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html). pub rustc::UNTRANSLATABLE_DIAGNOSTIC, Allow, "prevent creation of diagnostics which cannot be translated", @@ -332,6 +355,11 @@ declare_tool_lint! { } declare_tool_lint! { + /// The `diagnostic_outside_of_impl` lint detects diagnostics created manually, + /// and inside an `IntoDiagnostic`/`AddToDiagnostic` implementation, + /// or a `#[derive(Diagnostic)]`/`#[derive(Subdiagnostic)]` expansion. + /// + /// More details on diagnostics implementations can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html). pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL, Allow, "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls", @@ -358,7 +386,7 @@ impl LateLintPass<'_> for Diagnostics { for (hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { if let Some(owner_did) = hir_id.as_owner() { found_parent_with_attr = found_parent_with_attr - || cx.tcx.has_attr(owner_did.to_def_id(), sym::rustc_lint_diagnostics); + || cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics); } debug!(?parent); @@ -396,6 +424,8 @@ impl LateLintPass<'_> for Diagnostics { } declare_tool_lint! { + /// The `bad_opt_access` lint detects accessing options by field instead of + /// the wrapper function. pub rustc::BAD_OPT_ACCESS, Deny, "prevent using options by field access when there is a wrapper function", diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index b83a9665f..3eefd1b0e 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -25,7 +25,7 @@ declare_lint! { /// /// fn main() { /// #[warn(let_underscore_drop)] - /// // SomeStuct is dropped immediately instead of at end of scope, + /// // SomeStruct is dropped immediately instead of at end of scope, /// // so "Dropping SomeStruct" is printed before "end of main". /// // The order of prints would be reversed if SomeStruct was bound to /// // a name (such as "_foo"). diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index bc7488fab..bb863f095 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -3,7 +3,7 @@ use crate::{ fluent_generated as fluent, late::unerased_lint_store, lints::{ - DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint, + DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion, }, }; @@ -128,7 +128,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp }, warn_about_weird_lints: false, store, - registered_tools: &tcx.resolutions(()).registered_tools, + registered_tools: &tcx.registered_tools(()), }; builder.add_command_line(); @@ -156,7 +156,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe }, warn_about_weird_lints: false, store, - registered_tools: &tcx.resolutions(()).registered_tools, + registered_tools: &tcx.registered_tools(()), }; if owner == hir::CRATE_OWNER_ID { @@ -266,12 +266,12 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> { let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id else { bug!("unstable expectation id should already be mapped") }; let key = LintExpectationId::Unstable { attr_id, lint_index: None }; - if !self.unstable_to_stable_ids.contains_key(&key) { - self.unstable_to_stable_ids.insert( - key, - LintExpectationId::Stable { hir_id, attr_index, lint_index: None, attr_id: None }, - ); - } + self.unstable_to_stable_ids.entry(key).or_insert(LintExpectationId::Stable { + hir_id, + attr_index, + lint_index: None, + attr_id: None, + }); self.expectations.push((id.normalize(), expectation)); } @@ -612,7 +612,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { self.emit_spanned_lint( FORBIDDEN_LINT_GROUPS, src.span().into(), - OverruledAtributeLint { + OverruledAttributeLint { overruled: src.span(), lint_level: level.as_str(), lint_source: src.name(), diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 35dc533e5..b35785405 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -126,7 +126,7 @@ 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" } +fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { levels::provide(providers); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 20ab0af58..1d5e02369 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -806,9 +806,9 @@ pub struct TyQualified { pub struct LintPassByHand; #[derive(LintDiagnostic)] -#[diag(lint_non_existant_doc_keyword)] +#[diag(lint_non_existent_doc_keyword)] #[help] -pub struct NonExistantDocKeyword { +pub struct NonExistentDocKeyword { pub keyword: Symbol, } @@ -875,7 +875,7 @@ impl AddToDiagnostic for NonBindingLetSub { // levels.rs #[derive(LintDiagnostic)] #[diag(lint_overruled_attribute)] -pub struct OverruledAtributeLint<'a> { +pub struct OverruledAttributeLint<'a> { #[label] pub overruled: Span, pub lint_level: &'a str, @@ -947,7 +947,7 @@ pub struct CStringPtr { // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] -#[diag(lint_multple_supertrait_upcastable)] +#[diag(lint_multiple_supertrait_upcastable)] pub struct MultipleSupertraitUpcastable { pub ident: Ident, } @@ -1210,11 +1210,33 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { #[diag(lint_range_endpoint_out_of_range)] pub struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, - #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")] - pub suggestion: Span, - pub start: String, - pub literal: u128, - pub suffix: &'a str, + #[subdiagnostic] + pub sub: UseInclusiveRange<'a>, +} + +#[derive(Subdiagnostic)] +pub enum UseInclusiveRange<'a> { + #[suggestion( + lint_range_use_inclusive_range, + code = "{start}..={literal}{suffix}", + applicability = "machine-applicable" + )] + WithoutParen { + #[primary_span] + sugg: Span, + start: String, + literal: u128, + suffix: &'a str, + }, + #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")] + WithParen { + #[suggestion_part(code = "=")] + eq_sugg: Span, + #[suggestion_part(code = "{literal}{suffix}")] + lit_sugg: Span, + literal: u128, + suffix: &'a str, + }, } #[derive(LintDiagnostic)] @@ -1390,7 +1412,7 @@ pub struct UnusedOp<'a> { pub op: &'a str, #[label] pub label: Span, - #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")] + #[suggestion(style = "verbose", code = "let _ = ", applicability = "maybe-incorrect")] pub suggestion: Span, } @@ -1400,7 +1422,7 @@ pub struct UnusedResult<'a> { pub ty: Ty<'a>, } -// FIXME(davidtwco): this isn't properly translatable becauses of the +// FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings #[derive(LintDiagnostic)] #[diag(lint_unused_closure)] @@ -1411,7 +1433,7 @@ pub struct UnusedClosure<'a> { pub post: &'a str, } -// FIXME(davidtwco): this isn't properly translatable becauses of the +// FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings #[derive(LintDiagnostic)] #[diag(lint_unused_generator)] @@ -1422,7 +1444,7 @@ pub struct UnusedGenerator<'a> { pub post: &'a str, } -// FIXME(davidtwco): this isn't properly translatable becauses of the pre/post +// FIXME(davidtwco): this isn't properly translatable because of the pre/post // strings pub struct UnusedDef<'a, 'b> { pub pre: &'a str, @@ -1434,17 +1456,15 @@ pub struct UnusedDef<'a, 'b> { } #[derive(Subdiagnostic)] -pub enum UnusedDefSuggestion { - #[suggestion( - lint_suggestion, - style = "verbose", - code = "let _ = ", - applicability = "machine-applicable" - )] - Default { - #[primary_span] - span: Span, - }, +#[suggestion( + lint_suggestion, + style = "verbose", + code = "let _ = ", + applicability = "maybe-incorrect" +)] +pub struct UnusedDefSuggestion { + #[primary_span] + pub span: Span, } // Needed because of def_path_str diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs index 62e8b4fe9..7c692fee3 100644 --- a/compiler/rustc_lint/src/map_unit_fn.rs +++ b/compiler/rustc_lint/src/map_unit_fn.rs @@ -56,6 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { return; } let arg_ty = cx.typeck_results().expr_ty(&args[0]); + let default_span = args[0].span; 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(); @@ -64,7 +65,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { MAP_UNIT_FN, span, MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap(), + function_label: cx + .tcx + .span_of_impl(*id) + .unwrap_or(default_span), argument_label: args[0].span, map_label: arg_ty.default_span(cx.tcx), suggestion: path.ident.span, @@ -80,7 +84,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { MAP_UNIT_FN, span, MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap(), + function_label: cx + .tcx + .span_of_impl(*id) + .unwrap_or(default_span), argument_label: args[0].span, map_label: arg_ty.default_span(cx.tcx), suggestion: path.ident.span, diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index 3045fc1a4..4c25d94a1 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -2,9 +2,9 @@ use crate::lints::CStringPtr; use crate::LateContext; use crate::LateLintPass; use crate::LintContext; -use rustc_hir::{Expr, ExprKind, PathSegment}; +use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; -use rustc_span::{symbol::sym, ExpnKind, Span}; +use rustc_span::{symbol::sym, Span}; declare_lint! { /// The `temporary_cstring_as_ptr` lint detects getting the inner pointer of @@ -34,47 +34,14 @@ declare_lint! { declare_lint_pass!(TemporaryCStringAsPtr => [TEMPORARY_CSTRING_AS_PTR]); -fn in_macro(span: Span) -> bool { - if span.from_expansion() { - !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..)) - } else { - false - } -} - -fn first_method_call<'tcx>( - expr: &'tcx Expr<'tcx>, -) -> Option<(&'tcx PathSegment<'tcx>, &'tcx Expr<'tcx>)> { - if let ExprKind::MethodCall(path, receiver, args, ..) = &expr.kind { - if args.iter().any(|e| e.span.from_expansion()) || receiver.span.from_expansion() { - None - } else { - Some((path, *receiver)) - } - } else { - None - } -} - impl<'tcx> LateLintPass<'tcx> for TemporaryCStringAsPtr { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_macro(expr.span) { - return; - } - - match first_method_call(expr) { - Some((path, unwrap_arg)) if path.ident.name == sym::as_ptr => { - let as_ptr_span = path.ident.span; - match first_method_call(unwrap_arg) { - Some((path, receiver)) - if path.ident.name == sym::unwrap || path.ident.name == sym::expect => - { - lint_cstring_as_ptr(cx, as_ptr_span, receiver, unwrap_arg); - } - _ => return, - } - } - _ => return, + if let ExprKind::MethodCall(as_ptr_path, as_ptr_receiver, ..) = expr.kind + && as_ptr_path.ident.name == sym::as_ptr + && let ExprKind::MethodCall(unwrap_path, unwrap_receiver, ..) = as_ptr_receiver.kind + && (unwrap_path.ident.name == sym::unwrap || unwrap_path.ident.name == sym::expect) + { + lint_cstring_as_ptr(cx, as_ptr_path.ident.span, unwrap_receiver, as_ptr_receiver); } } } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index f130a9818..4af879b4e 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -250,7 +250,7 @@ impl EarlyLintPass for NonAsciiIdents { let latin_augmented_script_set = AugmentedScriptSet::for_char('A'); script_states.insert(latin_augmented_script_set, ScriptSetUsage::Verified); - let mut has_suspicous = false; + let mut has_suspicious = false; for (symbol, &sp) in symbols.iter() { let symbol_str = symbol.as_str(); for ch in symbol_str.chars() { @@ -278,14 +278,14 @@ impl EarlyLintPass for NonAsciiIdents { if !is_potential_mixed_script_confusable_char(ch) { ScriptSetUsage::Verified } else { - has_suspicous = true; + has_suspicious = true; ScriptSetUsage::Suspicious(vec![ch], sp) } }); } } - if has_suspicous { + if has_suspicious { let verified_augmented_script_sets = script_states .iter() .flat_map(|(k, v)| match v { diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 71e2e66bd..9efc14849 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -328,8 +328,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name { Some(Ident::from_str(name)) } else { - cx.sess() - .find_by_name(&cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name) + attr::find_by_name(&cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name) .and_then(|attr| attr.meta()) .and_then(|meta| { meta.name_value_literal().and_then(|lit| { @@ -384,9 +383,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { match &fk { FnKind::Method(ident, sig, ..) => match method_context(cx, id) { MethodLateContext::PlainImpl => { - if sig.header.abi != Abi::Rust - && cx.tcx.has_attr(id.to_def_id(), sym::no_mangle) - { + if sig.header.abi != Abi::Rust && cx.tcx.has_attr(id, sym::no_mangle) { return; } self.check_snake_case(cx, "method", ident); @@ -398,7 +395,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.tcx.has_attr(id.to_def_id(), sym::no_mangle) { + if header.abi != Abi::Rust && cx.tcx.has_attr(id, sym::no_mangle) { return; } self.check_snake_case(cx, "function", ident); @@ -491,7 +488,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { let attrs = cx.tcx.hir().attrs(it.hir_id()); match it.kind { - hir::ItemKind::Static(..) if !cx.sess().contains_name(attrs, sym::no_mangle) => { + hir::ItemKind::Static(..) if !attr::contains_name(attrs, sym::no_mangle) => { NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident); } hir::ItemKind::Const(..) => { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 883a56cb3..f9d43fe22 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -27,6 +27,8 @@ declare_lint! { /// ### Example /// /// ```rust + /// #![feature(type_alias_impl_trait)] + /// /// trait Duh {} /// /// impl Duh for i32 {} @@ -41,7 +43,9 @@ declare_lint! { /// type Assoc = F; /// } /// - /// fn test() -> impl Trait<Assoc = impl Sized> { + /// type Tait = impl Sized; + /// + /// fn test() -> impl Trait<Assoc = Tait> { /// 42 /// } /// ``` @@ -54,7 +58,7 @@ declare_lint! { /// /// Although the hidden type, `i32` does satisfy this bound, we do not /// consider the return type to be well-formed with this lint. It can be - /// fixed by changing `impl Sized` into `impl Sized + Send`. + /// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Send`. pub OPAQUE_HIDDEN_INFERRED_BOUND, Warn, "detects the use of nested `impl Trait` types in associated type bounds that are not general enough" @@ -64,7 +68,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]); impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; }; + let hir::ItemKind::OpaqueTy(opaque) = &item.kind else { return; }; let def_id = item.owner_id.def_id.to_def_id(); let infcx = &cx.tcx.infer_ctxt().build(); // For every projection predicate in the opaque type's explicit bounds, @@ -81,6 +85,17 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // have opaques in them anyways. let Some(proj_term) = proj.term.ty() else { continue }; + // HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"... + if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() + && cx.tcx.parent(opaque_ty.def_id) == def_id + && matches!( + opaque.origin, + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) + ) + { + continue; + } + let proj_ty = cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs); // For every instance of the projection type in the bounds, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 85958c417..a6ba74220 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -4,7 +4,8 @@ use crate::{ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, - OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag, + OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, + VariantSizeDifferencesDiag, }, }; use crate::{LateContext, LateLintPass, LintContext}; @@ -17,7 +18,7 @@ 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, TypeVisitableExt, + self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_span::def_id::LocalDefId; use rustc_span::source_map; @@ -136,6 +137,14 @@ fn lint_overflowing_range_endpoint<'tcx>( expr: &'tcx hir::Expr<'tcx>, ty: &str, ) -> bool { + // Look past casts to support cases like `0..256 as u8` + let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.hir().get(cx.tcx.hir().parent_id(expr.hir_id)) + && let ExprKind::Cast(_, _) = par_expr.kind { + (par_expr, expr.span) + } else { + (expr, expr.span) + }; + // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. let par_id = cx.tcx.hir().parent_id(expr.hir_id); @@ -155,7 +164,6 @@ fn lint_overflowing_range_endpoint<'tcx>( if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) { return false; }; - let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; use rustc_ast::{LitIntType, LitKind}; let suffix = match lit.node { @@ -164,16 +172,28 @@ fn lint_overflowing_range_endpoint<'tcx>( LitKind::Int(_, LitIntType::Unsuffixed) => "", _ => bug!(), }; - cx.emit_spanned_lint( - OVERFLOWING_LITERALS, - struct_expr.span, - RangeEndpointOutOfRange { - ty, - suggestion: struct_expr.span, + + let sub_sugg = if expr.span.lo() == lit_span.lo() { + let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; + UseInclusiveRange::WithoutParen { + sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()), start, literal: lit_val - 1, suffix, - }, + } + } else { + UseInclusiveRange::WithParen { + eq_sugg: expr.span.shrink_to_lo(), + lit_sugg: lit_span, + literal: lit_val - 1, + suffix, + } + }; + + cx.emit_spanned_lint( + OVERFLOWING_LITERALS, + struct_expr.span, + RangeEndpointOutOfRange { ty, sub: sub_sugg }, ); // We've just emitted a lint, special cased for `(...)..MAX+1` ranges, @@ -750,7 +770,7 @@ pub(crate) fn repr_nullable_ptr<'tcx>( debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty); if let ty::Adt(ty_def, substs) = ty.kind() { let field_ty = match &ty_def.variants().raw[..] { - [var_one, var_two] => match (&var_one.fields[..], &var_two.fields[..]) { + [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { ([], [field]) | ([field], []) => field.ty(cx.tcx, substs), _ => return None, }, diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 3a92f5806..28cc63198 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -12,9 +12,9 @@ use rustc_errors::{pluralize, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_infer::traits::util::elaborate_predicates_with_span; +use rustc_infer::traits::util::elaborate; use rustc_middle::ty::adjustment; -use rustc_middle::ty::{self, DefIdTree, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; @@ -103,8 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { && let ty = cx.typeck_results().expr_ty(&await_expr) && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind() && cx.tcx.ty_is_opaque_future(ty) - // FIXME: This also includes non-async fns that return `impl Future`. && let async_fn_def_id = cx.tcx.parent(*future_def_id) + && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn) + // Check that this `impl Future` actually comes from an `async fn` + && cx.tcx.asyncness(async_fn_def_id).is_async() && check_must_use_def( cx, async_fn_def_id, @@ -123,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span); let type_lint_emitted_or_suppressed = match must_use_result { Some(path) => { - emit_must_use_untranslated(cx, &path, "", "", 1); + emit_must_use_untranslated(cx, &path, "", "", 1, false); true } None => false, @@ -254,24 +256,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { - elaborate_predicates_with_span( - cx.tcx, - cx.tcx.explicit_item_bounds(def).iter().cloned(), - ) - .find_map(|obligation| { - // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::PredicateKind::Clause(ty::Clause::Trait( - ref poly_trait_predicate, - )) = obligation.predicate.kind().skip_binder() - { - let def_id = poly_trait_predicate.trait_ref.def_id; - - is_def_must_use(cx, def_id, span) - } else { - None - } - }) - .map(|inner| MustUsePath::Opaque(Box::new(inner))) + elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned()) + // We only care about self bounds for the impl-trait + .filter_only_self() + .find_map(|(pred, _span)| { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::PredicateKind::Clause(ty::Clause::Trait( + ref poly_trait_predicate, + )) = pred.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; + + is_def_must_use(cx, def_id, span) + } else { + None + } + }) + .map(|inner| MustUsePath::Opaque(Box::new(inner))) } ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() @@ -358,6 +359,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre_path, descr_post_path, 1, + false, ) }) .is_some() @@ -370,6 +372,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre: &str, descr_post: &str, plural_len: usize, + is_inner: bool, ) { let plural_suffix = pluralize!(plural_len); @@ -377,20 +380,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { MustUsePath::Suppressed => {} MustUsePath::Boxed(path) => { let descr_pre = &format!("{}boxed ", descr_pre); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::Opaque(path) => { let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::TraitObject(path) => { let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::TupleElement(elems) => { for (index, path) in elems { let descr_post = &format!(" in tuple element {}", index); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated( + cx, path, descr_pre, descr_post, plural_len, true, + ); } } MustUsePath::Array(path, len) => { @@ -401,6 +406,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre, descr_post, plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), + true, ); } MustUsePath::Closure(span) => { @@ -418,19 +424,6 @@ 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, @@ -440,7 +433,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx, def_id: *def_id, note: *reason, - suggestion, + suggestion: (!is_inner) + .then_some(UnusedDefSuggestion { span: span.shrink_to_lo() }), }, ); } @@ -812,7 +806,9 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind { + if let Const(box ast::ConstItem { expr: Some(expr), .. }) + | Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind + { self.check_unused_delims_expr( cx, expr, @@ -1349,9 +1345,8 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(box_syntax)] /// fn main() { - /// let a = (box [1, 2, 3]).len(); + /// let a = Box::new([1, 2, 3]).len(); /// } /// ``` /// @@ -1372,7 +1367,11 @@ declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]); impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { match e.kind { - hir::ExprKind::Box(_) => {} + hir::ExprKind::Call(path_expr, [_]) + if let hir::ExprKind::Path(qpath) = &path_expr.kind + && let Some(did) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::box_new, did) + => {} _ => return, } |