summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_lint
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
commit631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch)
treea1b87c8f8cad01cf18f7c5f57a08f102771ed303 /compiler/rustc_lint
parentAdding debian version 1.69.0+dfsg1-1. (diff)
downloadrustc-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.rs66
-rw-r--r--compiler/rustc_lint/src/context.rs4
-rw-r--r--compiler/rustc_lint/src/early.rs13
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs11
-rw-r--r--compiler/rustc_lint/src/internal.rs36
-rw-r--r--compiler/rustc_lint/src/let_underscore.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs20
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/lints.rs68
-rw-r--r--compiler/rustc_lint/src/map_unit_fn.rs11
-rw-r--r--compiler/rustc_lint/src/methods.rs49
-rw-r--r--compiler/rustc_lint/src/non_ascii_idents.rs6
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs11
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs21
-rw-r--r--compiler/rustc_lint/src/types.rs42
-rw-r--r--compiler/rustc_lint/src/unused.rs87
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,
}