Skip to content

Use is_lang_item and as_lang_item instead of handrolling their logic #140160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_hir as hir;
use rustc_hir::GenericArg;
use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::def_id::DefId;
use rustc_middle::span_bug;
use rustc_middle::{span_bug, ty};
use rustc_session::parse::add_feature_diagnostics;
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
use smallvec::{SmallVec, smallvec};
Expand Down Expand Up @@ -590,14 +590,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<DefId> {
let lang_items = self.tcx.lang_items();
if Some(def_id) == lang_items.fn_trait() {
lang_items.async_fn_trait()
} else if Some(def_id) == lang_items.fn_mut_trait() {
lang_items.async_fn_mut_trait()
} else if Some(def_id) == lang_items.fn_once_trait() {
lang_items.async_fn_once_trait()
} else {
None
match self.tcx.fn_trait_kind_from_def_id(def_id)? {
ty::ClosureKind::Fn => lang_items.async_fn_trait(),
ty::ClosureKind::FnMut => lang_items.async_fn_mut_trait(),
ty::ClosureKind::FnOnce => lang_items.async_fn_once_trait(),
}
}
}
7 changes: 1 addition & 6 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1265,12 +1265,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
&& let CallKind::FnCall { fn_trait_id, self_ty } = kind
&& let ty::Param(_) = self_ty.kind()
&& ty == self_ty
&& [
self.infcx.tcx.lang_items().fn_once_trait(),
self.infcx.tcx.lang_items().fn_mut_trait(),
self.infcx.tcx.lang_items().fn_trait(),
]
.contains(&Some(fn_trait_id))
&& self.infcx.tcx.fn_trait_kind_from_def_id(fn_trait_id).is_some()
{
// Do not suggest `F: FnOnce() + Clone`.
false
Expand Down
60 changes: 26 additions & 34 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

use rustc_abi::ExternAbi;
use rustc_errors::DiagMessage;
use rustc_hir::{self as hir};
use rustc_middle::bug;
use rustc_hir::{self as hir, LangItem};
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefId;
Expand Down Expand Up @@ -173,23 +172,22 @@ pub(crate) fn check_intrinsic_type(
ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
]);
let mk_va_list_ty = |mutbl| {
tcx.lang_items().va_list().map(|did| {
let region = ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
);
let env_region = ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_u32(2),
kind: ty::BoundRegionKind::ClosureEnv,
},
);
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
})
let did = tcx.require_lang_item(LangItem::VaList, Some(span));
let region = ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
);
let env_region = ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_u32(2),
kind: ty::BoundRegionKind::ClosureEnv,
},
);
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
};

let (n_tps, n_lts, n_cts, inputs, output, safety) = if name_str.starts_with("atomic_") {
Expand Down Expand Up @@ -548,23 +546,17 @@ pub(crate) fn check_intrinsic_type(
)
}

sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
Some((va_list_ref_ty, _)) => (0, 0, vec![va_list_ref_ty], tcx.types.unit),
None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
},
sym::va_start | sym::va_end => {
(0, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], tcx.types.unit)
}

sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
Some((va_list_ref_ty, va_list_ty)) => {
let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
(0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
}
None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
},
sym::va_copy => {
let (va_list_ref_ty, va_list_ty) = mk_va_list_ty(hir::Mutability::Not);
let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
(0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
}

sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) {
Some((va_list_ref_ty, _)) => (1, 0, vec![va_list_ref_ty], param(0)),
None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
},
sym::va_arg => (1, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], param(0)),

sym::nontemporal_store => {
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
ObligationCause::misc(impl_span, checker.impl_def_id),
param_env,
nontrivial_field_ty,
tcx.lang_items().pointer_like().unwrap(),
tcx.require_lang_item(LangItem::PointerLike, Some(impl_span)),
);
// FIXME(dyn-star): We should regionck this implementation.
if ocx.select_all_or_error().is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub(crate) fn check_legal_trait_for_method_call(
body_id: DefId,
) -> Result<(), ErrorGuaranteed> {
if tcx.is_lang_item(trait_id, LangItem::Drop)
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
&& !tcx.is_lang_item(body_id, LangItem::FallbackSurfaceDrop)
{
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
errors::ExplicitDestructorCallSugg::Snippet {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
if let ty::Adt(adt, _) = ty.kind()
&& self.tcx().lang_items().get(hir::LangItem::RangeFull) == Some(adt.did())
&& self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
&& let hir::ExprKind::Struct(
hir::QPath::LangItem(hir::LangItem::RangeFull, _),
[],
Expand Down
21 changes: 12 additions & 9 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1457,15 +1457,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => (None, None),
};

let ranges = &[
self.tcx.lang_items().range_struct(),
self.tcx.lang_items().range_from_struct(),
self.tcx.lang_items().range_to_struct(),
self.tcx.lang_items().range_full_struct(),
self.tcx.lang_items().range_inclusive_struct(),
self.tcx.lang_items().range_to_inclusive_struct(),
];
if type_def_id != None && ranges.contains(&type_def_id) {
let is_range = match type_def_id.and_then(|id| self.tcx.as_lang_item(id)) {
Some(
LangItem::Range
| LangItem::RangeFrom
| LangItem::RangeTo
| LangItem::RangeFull
| LangItem::RangeInclusiveStruct
| LangItem::RangeToInclusive,
) => true,
_ => false,
};
if is_range {
if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
let msg = "constants only support matching by type, \
if you meant to match against a range of values, \
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use std::cell::RefCell;
use std::ops::Deref;

use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{HirId, HirIdMap};
use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
Expand Down Expand Up @@ -137,7 +136,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
obligation.predicate.kind().skip_binder()
&& let Some(ty) =
self.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| self.root_var(t))
&& self.tcx.lang_items().sized_trait().is_some_and(|st| st != tpred.trait_ref.def_id)
&& !self.tcx.is_lang_item(tpred.trait_ref.def_id, LangItem::Sized)
{
let new_self_ty = self.tcx.types.unit;

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/shadowed_into_iter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_hir as hir;
use rustc_hir::{self as hir, LangItem};
use rustc_middle::ty::{self, Ty};
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, impl_lint_pass};
Expand Down Expand Up @@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else {
return;
};
if Some(method_def_id) != cx.tcx.lang_items().into_iter_fn() {
if !cx.tcx.is_lang_item(method_def_id, LangItem::IntoIterIntoIter) {
return;
}

Expand Down
18 changes: 8 additions & 10 deletions compiler/rustc_middle/src/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// returns a corresponding [`ty::ClosureKind`].
/// For any other [`DefId`] return `None`.
pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
let items = self.lang_items();
match Some(id) {
x if x == items.fn_trait() => Some(ty::ClosureKind::Fn),
x if x == items.fn_mut_trait() => Some(ty::ClosureKind::FnMut),
x if x == items.fn_once_trait() => Some(ty::ClosureKind::FnOnce),
match self.as_lang_item(id)? {
LangItem::Fn => Some(ty::ClosureKind::Fn),
LangItem::FnMut => Some(ty::ClosureKind::FnMut),
LangItem::FnOnce => Some(ty::ClosureKind::FnOnce),
_ => None,
}
}
Expand All @@ -48,11 +47,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// returns a corresponding [`ty::ClosureKind`].
/// For any other [`DefId`] return `None`.
pub fn async_fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
let items = self.lang_items();
match Some(id) {
x if x == items.async_fn_trait() => Some(ty::ClosureKind::Fn),
x if x == items.async_fn_mut_trait() => Some(ty::ClosureKind::FnMut),
x if x == items.async_fn_once_trait() => Some(ty::ClosureKind::FnOnce),
match self.as_lang_item(id)? {
LangItem::AsyncFn => Some(ty::ClosureKind::Fn),
LangItem::AsyncFnMut => Some(ty::ClosureKind::FnMut),
LangItem::AsyncFnOnce => Some(ty::ClosureKind::FnOnce),
_ => None,
}
}
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1774,9 +1774,7 @@ impl<'tcx> Ty<'tcx> {
match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
Ok(metadata_ty) => metadata_ty,
Err(tail_ty) => {
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
bug!("No metadata_type lang item while looking at {self:?}")
};
let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
Ty::new_projection(tcx, metadata_def_id, [tail_ty])
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/check_call_recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::ops::ControlFlow;
use rustc_data_structures::graph::iterate::{
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
};
use rustc_hir::LangItem;
use rustc_hir::def::DefKind;
use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind};
use rustc_middle::ty::{self, GenericArg, GenericArgs, Instance, Ty, TyCtxt};
Expand Down Expand Up @@ -44,8 +45,7 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
if let DefKind::AssocFn = tcx.def_kind(def_id)
&& let Some(trait_ref) =
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
&& drop_trait == trait_ref.instantiate_identity().def_id
&& tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop)
// avoid erroneous `Drop` impls from causing ICEs below
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
&& sig.inputs().skip_binder().len() == 1
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_monomorphize/src/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ where
match mono_item.instantiation_mode(cx.tcx) {
InstantiationMode::GloballyShared { .. } => {}
InstantiationMode::LocalCopy => {
if Some(mono_item.def_id()) != cx.tcx.lang_items().start_fn() {
if !cx.tcx.is_lang_item(mono_item.def_id(), LangItem::Start) {
continue;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -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());
Expand Down
Loading
Loading