about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorOli Scherer <github333195615777966@oli-obk.de>2025-04-22 09:50:49 +0000
committerOli Scherer <github333195615777966@oli-obk.de>2025-04-22 11:02:37 +0000
commit5d2952100f587ee1badfd39280e6c90a28e35c3a (patch)
tree78346d72f5c35cc937f8d08b49cb3a3306363820 /compiler/rustc_trait_selection/src
parent9bfa31f632912180dc742809bcc51a97f2d7079d (diff)
Use `is_lang_item` and `as_lang_item` instead of handrolling their logic
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs10
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs240
5 files changed, 130 insertions, 137 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
index 1c3e570b676..d8b405e904c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
@@ -81,9 +81,7 @@ pub fn call_kind<'tcx>(
         }
     });
 
-    let fn_call = parent.and_then(|p| {
-        lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
-    });
+    let fn_call = parent.filter(|&p| tcx.fn_trait_kind_from_def_id(p).is_some());
 
     let operator = if !from_hir_call && let Some(p) = parent {
         lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 5648021f613..df6e8fc4503 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -146,7 +146,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             && leaf_trait_predicate.def_id() != root_pred.def_id()
                             // The root trait is not `Unsize`, as to avoid talking about it in
                             // `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
-                            && Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
+                            && !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize)
                         {
                             (
                                 self.resolve_vars_if_possible(
@@ -2274,10 +2274,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // auto-traits or fundamental traits that might not be exactly what
         // the user might expect to be presented with. Instead this is
         // useful for less general traits.
-        if peeled
-            && !self.tcx.trait_is_auto(def_id)
-            && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
-        {
+        if peeled && !self.tcx.trait_is_auto(def_id) && self.tcx.as_lang_item(def_id).is_none() {
             let impl_candidates = self.find_similar_impl_candidates(trait_pred);
             self.report_similar_impl_candidates(
                 &impl_candidates,
@@ -3013,8 +3010,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // This shouldn't be common unless manually implementing one of the
         // traits manually, but don't make it more confusing when it does
         // happen.
-        if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
-        {
+        if !self.tcx.is_lang_item(expected_trait_ref.def_id, LangItem::Coroutine) && not_tupled {
             return Ok(self.report_and_explain_type_error(
                 TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref),
                 obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 7d95a7b3fed..de251ae2893 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3844,12 +3844,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     );
                     if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
                         && let ty::ClauseKind::Trait(pred) = clause
-                        && [
-                            tcx.lang_items().fn_once_trait(),
-                            tcx.lang_items().fn_mut_trait(),
-                            tcx.lang_items().fn_trait(),
-                        ]
-                        .contains(&Some(pred.def_id()))
+                        && tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some()
                     {
                         if let [stmt, ..] = block.stmts
                             && let hir::StmtKind::Semi(value) = stmt.kind
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index d8dcd12aecb..6f1a8683a65 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -1,5 +1,6 @@
 use std::ops::ControlFlow;
 
+use rustc_hir::LangItem;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
 use rustc_infer::traits::{
@@ -452,9 +453,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
         // We do this as a separate loop so that we do not choose to tell the user about some nested
         // goal before we encounter a `T: FnPtr` nested goal.
         for nested_goal in &nested_goals {
-            if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait()
-                && let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
-                && poly_trait_pred.def_id() == fn_ptr_trait
+            if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
+                && tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
                 && let Err(NoSolution) = nested_goal.result()
             {
                 return ControlFlow::Break(self.obligation.clone());
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 0dce504903c..99fa791b375 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -965,36 +965,38 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
 
                 let tcx = selcx.tcx();
-                let lang_items = selcx.tcx().lang_items();
-                if [
-                    lang_items.coroutine_trait(),
-                    lang_items.future_trait(),
-                    lang_items.iterator_trait(),
-                    lang_items.async_iterator_trait(),
-                    lang_items.fn_trait(),
-                    lang_items.fn_mut_trait(),
-                    lang_items.fn_once_trait(),
-                    lang_items.async_fn_trait(),
-                    lang_items.async_fn_mut_trait(),
-                    lang_items.async_fn_once_trait(),
-                ]
-                .contains(&Some(trait_ref.def_id))
-                {
-                    true
-                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncFnKindHelper) {
-                    // FIXME(async_closures): Validity constraints here could be cleaned up.
-                    if obligation.predicate.args.type_at(0).is_ty_var()
-                        || obligation.predicate.args.type_at(4).is_ty_var()
-                        || obligation.predicate.args.type_at(5).is_ty_var()
-                    {
-                        candidate_set.mark_ambiguous();
-                        true
-                    } else {
-                        obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
-                            && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
+                match selcx.tcx().as_lang_item(trait_ref.def_id) {
+                    Some(
+                        LangItem::Coroutine
+                        | LangItem::Future
+                        | LangItem::Iterator
+                        | LangItem::AsyncIterator
+                        | LangItem::Fn
+                        | LangItem::FnMut
+                        | LangItem::FnOnce
+                        | LangItem::AsyncFn
+                        | LangItem::AsyncFnMut
+                        | LangItem::AsyncFnOnce,
+                    ) => true,
+                    Some(LangItem::AsyncFnKindHelper) => {
+                        // FIXME(async_closures): Validity constraints here could be cleaned up.
+                        if obligation.predicate.args.type_at(0).is_ty_var()
+                            || obligation.predicate.args.type_at(4).is_ty_var()
+                            || obligation.predicate.args.type_at(5).is_ty_var()
+                        {
+                            candidate_set.mark_ambiguous();
+                            true
+                        } else {
+                            obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
+                                && obligation
+                                    .predicate
+                                    .args
+                                    .type_at(1)
+                                    .to_opt_closure_kind()
+                                    .is_some()
+                        }
                     }
-                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::DiscriminantKind) {
-                    match self_ty.kind() {
+                    Some(LangItem::DiscriminantKind) => match self_ty.kind() {
                         ty::Bool
                         | ty::Char
                         | ty::Int(_)
@@ -1031,9 +1033,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Placeholder(..)
                         | ty::Infer(..)
                         | ty::Error(_) => false,
-                    }
-                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncDestruct) {
-                    match self_ty.kind() {
+                    },
+                    Some(LangItem::AsyncDestruct) => match self_ty.kind() {
                         ty::Bool
                         | ty::Char
                         | ty::Int(_)
@@ -1068,101 +1069,104 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Placeholder(..)
                         | ty::Infer(_)
                         | ty::Error(_) => false,
-                    }
-                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) {
-                    let tail = selcx.tcx().struct_tail_raw(
-                        self_ty,
-                        |ty| {
-                            // We throw away any obligations we get from this, since we normalize
-                            // and confirm these obligations once again during confirmation
-                            normalize_with_depth(
-                                selcx,
-                                obligation.param_env,
-                                obligation.cause.clone(),
-                                obligation.recursion_depth + 1,
-                                ty,
-                            )
-                            .value
-                        },
-                        || {},
-                    );
+                    },
+                    Some(LangItem::PointeeTrait) => {
+                        let tail = selcx.tcx().struct_tail_raw(
+                            self_ty,
+                            |ty| {
+                                // We throw away any obligations we get from this, since we normalize
+                                // and confirm these obligations once again during confirmation
+                                normalize_with_depth(
+                                    selcx,
+                                    obligation.param_env,
+                                    obligation.cause.clone(),
+                                    obligation.recursion_depth + 1,
+                                    ty,
+                                )
+                                .value
+                            },
+                            || {},
+                        );
 
-                    match tail.kind() {
-                        ty::Bool
-                        | ty::Char
-                        | ty::Int(_)
-                        | ty::Uint(_)
-                        | ty::Float(_)
-                        | ty::Str
-                        | ty::Array(..)
-                        | ty::Pat(..)
-                        | ty::Slice(_)
-                        | ty::RawPtr(..)
-                        | ty::Ref(..)
-                        | ty::FnDef(..)
-                        | ty::FnPtr(..)
-                        | ty::Dynamic(..)
-                        | ty::Closure(..)
-                        | ty::CoroutineClosure(..)
-                        | ty::Coroutine(..)
-                        | ty::CoroutineWitness(..)
-                        | ty::Never
-                        // Extern types have unit metadata, according to RFC 2850
-                        | ty::Foreign(_)
-                        // If returned by `struct_tail` this is a unit struct
-                        // without any fields, or not a struct, and therefore is Sized.
-                        | ty::Adt(..)
-                        // If returned by `struct_tail` this is the empty tuple.
-                        | ty::Tuple(..)
-                        // Integers and floats are always Sized, and so have unit type metadata.
-                        | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
-                        // This happens if we reach the recursion limit when finding the struct tail.
-                        | ty::Error(..) => true,
-
-                        // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
-                        // Otherwise, type parameters, opaques, and unnormalized projections have
-                        // unit metadata if they're known (e.g. by the param_env) to be sized.
-                        ty::Param(_) | ty::Alias(..)
-                            if self_ty != tail
-                                || selcx.infcx.predicate_must_hold_modulo_regions(
-                                    &obligation.with(
-                                        selcx.tcx(),
-                                        ty::TraitRef::new(
+                        match tail.kind() {
+                            ty::Bool
+                            | ty::Char
+                            | ty::Int(_)
+                            | ty::Uint(_)
+                            | ty::Float(_)
+                            | ty::Str
+                            | ty::Array(..)
+                            | ty::Pat(..)
+                            | ty::Slice(_)
+                            | ty::RawPtr(..)
+                            | ty::Ref(..)
+                            | ty::FnDef(..)
+                            | ty::FnPtr(..)
+                            | ty::Dynamic(..)
+                            | ty::Closure(..)
+                            | ty::CoroutineClosure(..)
+                            | ty::Coroutine(..)
+                            | ty::CoroutineWitness(..)
+                            | ty::Never
+                            // Extern types have unit metadata, according to RFC 2850
+                            | ty::Foreign(_)
+                            // If returned by `struct_tail` this is a unit struct
+                            // without any fields, or not a struct, and therefore is Sized.
+                            | ty::Adt(..)
+                            // If returned by `struct_tail` this is the empty tuple.
+                            | ty::Tuple(..)
+                            // Integers and floats are always Sized, and so have unit type metadata.
+                            | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
+                            // This happens if we reach the recursion limit when finding the struct tail.
+                            | ty::Error(..) => true,
+
+                            // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
+                            // Otherwise, type parameters, opaques, and unnormalized projections have
+                            // unit metadata if they're known (e.g. by the param_env) to be sized.
+                            ty::Param(_) | ty::Alias(..)
+                                if self_ty != tail
+                                    || selcx.infcx.predicate_must_hold_modulo_regions(
+                                        &obligation.with(
                                             selcx.tcx(),
-                                            selcx.tcx().require_lang_item(
-                                                LangItem::Sized,
-                                                Some(obligation.cause.span),
+                                            ty::TraitRef::new(
+                                                selcx.tcx(),
+                                                selcx.tcx().require_lang_item(
+                                                    LangItem::Sized,
+                                                    Some(obligation.cause.span),
+                                                ),
+                                                [self_ty],
                                             ),
-                                            [self_ty],
                                         ),
-                                    ),
-                                ) =>
-                        {
-                            true
-                        }
+                                    ) =>
+                            {
+                                true
+                            }
 
-                        ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
+                            ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
 
-                        // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
-                        ty::Param(_)
-                        | ty::Alias(..)
-                        | ty::Bound(..)
-                        | ty::Placeholder(..)
-                        | ty::Infer(..) => {
-                            if tail.has_infer_types() {
-                                candidate_set.mark_ambiguous();
+                            // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
+                            ty::Param(_)
+                            | ty::Alias(..)
+                            | ty::Bound(..)
+                            | ty::Placeholder(..)
+                            | ty::Infer(..) => {
+                                if tail.has_infer_types() {
+                                    candidate_set.mark_ambiguous();
+                                }
+                                false
                             }
-                            false
                         }
                     }
-                } else if tcx.trait_is_auto(trait_ref.def_id) {
-                    tcx.dcx().span_delayed_bug(
-                        tcx.def_span(obligation.predicate.def_id),
-                        "associated types not allowed on auto traits",
-                    );
-                    false
-                } else {
-                    bug!("unexpected builtin trait with associated type: {trait_ref:?}")
+                    _ if tcx.trait_is_auto(trait_ref.def_id) => {
+                        tcx.dcx().span_delayed_bug(
+                            tcx.def_span(obligation.predicate.def_id),
+                            "associated types not allowed on auto traits",
+                        );
+                        false
+                    }
+                    _ => {
+                        bug!("unexpected builtin trait with associated type: {trait_ref:?}")
+                    }
                 }
             }
             ImplSource::Param(..) => {