Skip to content

Commit

Permalink
Make Iterator a lang item
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Oct 23, 2023
1 parent 4c11e0e commit 6ea822c
Show file tree
Hide file tree
Showing 23 changed files with 34 additions and 28 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}`"
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
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.
Expand Down
3 changes: 1 addition & 2 deletions src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions src/tools/clippy/clippy_lints/src/copy_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/loops/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions src/tools/clippy/clippy_lints/src/methods/filter_next.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
/// Checks if `<iter_ty as Iterator>::Item` is the same as `<collect_ty as IntoIter>::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])
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion src/tools/clippy/clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Ty<'tcx>> {
cx.tcx
.get_diagnostic_item(sym::Iterator)
.lang_items().iterator_trait()
.and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item"))
}

Expand Down

0 comments on commit 6ea822c

Please sign in to comment.