diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index e61653c310921..149bc69f6f954 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1414,7 +1414,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { && let Some(loop_span) = finder.loop_span && let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id) && let Some(trait_did) = tcx.trait_of_item(def_id) - && tcx.is_diagnostic_item(sym::Iterator, trait_did) + && tcx.lang_items().iterator_trait() == Some(trait_did) { if let Some(loop_bind) = finder.loop_bind { err.note(format!( @@ -2457,7 +2457,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; // to avoid panics - if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) + if let Some(iter_trait) = tcx.lang_items().iterator_trait() && self .infcx .type_implements_trait(iter_trait, [return_ty], self.param_env) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index cdfc67d5740f6..c8ac95e29949b 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -210,6 +210,7 @@ language_item_table! { FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; + Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0); Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); CoroutineState, sym::coroutine_state, gen_state, Target::Enum, GenericRequirement::None; Coroutine, sym::coroutine, gen_trait, Target::Trait, GenericRequirement::Minimum(1); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 640138a3e5eff..c2895dc580130 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1294,7 +1294,7 @@ fn suggest_impl_trait<'tcx>( for (trait_def_id, assoc_item_def_id, formatter) in [ ( - tcx.get_diagnostic_item(sym::Iterator), + tcx.lang_items().iterator_trait(), tcx.get_diagnostic_item(sym::IteratorItem), format_as_assoc, ), diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3ed22e095e89c..022c8c9c7a204 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -549,7 +549,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { err.span_label(span, msg); } - if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) { + if let Some(iterator_trait) = self.tcx.lang_items().iterator_trait() { let iterator_trait = self.tcx.def_path_str(iterator_trait); err.note(format!( "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement" diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7a7e9024bd88c..b1e187980a755 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -852,6 +852,9 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // This check has to be run after all lints are done processing. We don't // define a lint filter, as all lint checks should have finished at this point. sess.time("check_lint_expectations", || tcx.ensure().check_expectations(None)); + + // Make sure we check for diagnostic item conflicts between different crates. + let _ = tcx.all_diagnostic_items(()); }); if sess.opts.unstable_opts.print_vtable_sizes { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6f6150a4172f5..541ed18d9ff4f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -685,7 +685,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { // We shouldn't recommend implementing `Copy` on stateful things, // such as iterators. - if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) + if let Some(iter_trait) = cx.tcx.lang_items().iterator_trait() && cx .tcx .infer_ctxt() diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 87c735eb5d60b..9337b1240ecb7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1522,7 +1522,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \ resolves to `{normalized_ty}`" )) - } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) { + } else if Some(trait_def_id) == self.tcx.lang_items().iterator_trait() { Some(format!( "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \ yields `{normalized_ty}`" diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c7ace58afa866..2393c5b5a61fc 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -69,7 +69,7 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} message = "`{Self}` is not an iterator" )] #[doc(notable_trait)] -#[rustc_diagnostic_item = "Iterator"] +#[cfg_attr(not(bootstrap), lang = "iterator")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator { /// The type of the elements being iterated over. diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs index 1593d7b0fb386..525dc74037a77 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs @@ -10,7 +10,6 @@ use rustc_hir::{BlockCheckMode, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -118,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions { if let Some(parent) = get_parent_expr(cx, e); if let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind; let caller = cx.typeck_results().expr_ty(self_arg); - if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + if let Some(iter_id) = cx.tcx.lang_items().iterator_trait(); if implements_trait(cx, caller, iter_id, &[]); then { return ControlFlow::Continue(Descend::No); diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index 5d04ad0112d50..4efaa14c857d0 100644 --- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs @@ -3,7 +3,6 @@ use clippy_utils::ty::is_copy; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; use if_chain::if_chain; @@ -46,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyIterator { let ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); if is_copy(cx, ty); if let Some(trait_id) = trait_ref.trait_def_id(); - if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id); + if cx.tcx.lang_items().iterator_trait() == Some(trait_id); then { span_lint_and_note( cx, diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index 066d2c4b7874f..2d03a3e304bae 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -5,7 +5,6 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::{FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does @@ -78,7 +77,7 @@ fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefI .unwrap_or(ret_ty); if cx .tcx - .get_diagnostic_item(sym::Iterator) + .lang_items().iterator_trait() .map_or(false, |iter_id| !implements_trait(cx, ret_ty, iter_id, &[])) { span_lint( diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 0ee291a4e9da9..31978fed10f4b 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -212,7 +212,7 @@ impl {self_ty_without_ref} {{ ) && let ref_ty = sig.inputs()[0] && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) - && let Some(iterator_did) = cx.tcx.get_diagnostic_item(sym::Iterator) + && let Some(iterator_did) = cx.tcx.lang_items().iterator_trait() && let ret_ty = sig.output() // Order is important here, we need to check that the `fn iter` return type actually implements `IntoIterator` // *before* normalizing `<_ as IntoIterator>::Item` (otherwise make_normalized_projection ICEs) diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index 0a2bd89eb3cd3..39dad86f36a69 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -9,7 +9,7 @@ use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{Symbol}; use std::iter::Iterator; #[derive(Debug, PartialEq, Eq)] @@ -316,7 +316,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the /// actual `Iterator` that the loop uses. pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String { - let impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| { + let impls_iterator = cx.tcx.lang_items().iterator_trait().map_or(false, |id| { implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[]) }); if impls_iterator { diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs index ac7bc9bcca47f..4400c8a14b109 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs @@ -5,7 +5,6 @@ use rustc_ast::{BindingAnnotation, Mutability}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::sym; use super::FILTER_NEXT; @@ -32,7 +31,7 @@ pub(super) fn check<'tcx>( filter_arg: &'tcx hir::Expr<'_>, ) { // lint if caller of `.filter().next()` is an Iterator - let recv_impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| { + let recv_impls_iterator = cx.tcx.lang_items().iterator_trait().map_or(false, |id| { implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[]) }); if recv_impls_iterator { diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 4040d3a5fe13b..2407da9851a40 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp if is_path_diagnostic_item(cx, func, sym::from_iter_fn); let ty = cx.typeck_results().expr_ty(expr); let arg_ty = cx.typeck_results().expr_ty(&args[0]); - if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + if let Some(iter_id) = cx.tcx.lang_items().iterator_trait(); if implements_trait(cx, arg_ty, iter_id, &[]); then { diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index a49dd98db8713..7cb91e3fa481e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -43,7 +43,7 @@ pub(super) fn check<'tcx>( needs_into_iter: bool, ) { let typeck = cx.typeck_results(); - if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator) + if let Some(iter_id) = cx.tcx.lang_items().iterator_trait() && let Some(method_id) = typeck.type_dependent_def_id(expr.hir_id) && cx.tcx.trait_of_item(method_id) == Some(iter_id) && let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id) diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs index ab13d30d84529..9d05cc28ae9f0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs @@ -60,7 +60,7 @@ pub(super) fn check( if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat); if is_type_lang_item(cx, cx.typeck_results().expr_ty(collect_expr), LangItem::String); if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id); - if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + if let Some(iter_trait_id) = cx.tcx.lang_items().iterator_trait(); if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id); if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg); let ctxt = collect_expr.span.ctxt(); diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index dbd965d650601..139b6c1f0229e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -208,7 +208,7 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool { /// Checks if `::Item` is the same as `::Item` fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool { let item = Symbol::intern("Item"); - if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) + if let Some(iter_trait) = cx.tcx.lang_items().iterator_trait() && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator) && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, item, [iter_ty]) && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty]) @@ -232,7 +232,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - && sig.skip_binder().output().is_bool() && let [_, search_ty] = *sig.skip_binder().inputs() && let ty::Ref(_, search_ty, Mutability::Not) = *cx.tcx.erase_late_bound_regions(sig.rebind(search_ty)).kind() - && let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) + && let Some(iter_trait) = cx.tcx.lang_items().iterator_trait() && let Some(iter_item) = cx.tcx .associated_items(iter_trait) .find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait) diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 7016ad0a80f15..06f48879a9cb5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -293,7 +293,7 @@ fn parse_iter_usage<'tcx>( return None; }; let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?; - let iter_id = cx.tcx.get_diagnostic_item(sym::Iterator)?; + let iter_id = cx.tcx.lang_items().iterator_trait()?; match (name.ident.as_str(), args) { ("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => (IterUsageKind::Nth(0), e.span), diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 0c72c13a3caa7..3b4bcb0db2420 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -47,7 +47,7 @@ pub fn check_for_loop_iter( if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind; if maybe_iter_method_name.ident.name == sym::iter; - if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + if let Some(iterator_trait_id) = cx.tcx.lang_items().iterator_trait(); let receiver_ty = cx.typeck_results().expr_ty(receiver); if implements_trait(cx, receiver_ty, iterator_trait_id, &[]); if let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 50d6f3b7e55f5..fb39fb1e49a21 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -212,7 +212,7 @@ fn check_into_iter_call_arg( if let Some(parent) = get_parent_expr(cx, expr); if let Some(callee_def_id) = fn_def_id(cx, parent); if is_into_iter(cx, callee_def_id); - if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + if let Some(iterator_trait_id) = cx.tcx.lang_items().iterator_trait(); let parent_ty = cx.typeck_results().expr_ty(parent); if implements_trait(cx, parent_ty, iterator_trait_id, &[]); if let Some(item_ty) = get_iterator_item_ty(cx, parent_ty); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 93b3702282288..7d5a86cbb2b3b 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -314,7 +314,13 @@ pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbo /// Checks if a method is in a diagnostic item trait pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool { if let Some(trait_did) = cx.tcx.trait_of_item(def_id) { - return cx.tcx.is_diagnostic_item(diag_item, trait_did); + // `Iterator` is a lang item, not a diag item, but we'd like to check for `Iterator` methods + // the same way we check for other traits' methods. + if diag_item == sym::Iterator { + return cx.tcx.lang_items().iterator_trait() == Some(trait_did) + } else { + return cx.tcx.is_diagnostic_item(diag_item, trait_did); + } } false } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 673b259523e18..26d4f8663b470 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -141,7 +141,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' /// Do not invoke without first verifying that the type implements `Iterator` pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { cx.tcx - .get_diagnostic_item(sym::Iterator) + .lang_items().iterator_trait() .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item")) }