Skip to content

Commit b3dc06f

Browse files
committed
Auto merge of #140160 - oli-obk:lang-items, r=<try>
Use `is_lang_item` and `as_lang_item` instead of handrolling their logic Various cleanups and deduplication. Most notably `if is_lang_item(foo, bar) {} else if is_lang_item...` chains are turned into matches. No behaviour changes intended beyond turning ICEs into fatal "lang item not found" errors
2 parents 8bf5a8d + 5d29521 commit b3dc06f

File tree

18 files changed

+193
-219
lines changed

18 files changed

+193
-219
lines changed

compiler/rustc_ast_lowering/src/path.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hir as hir;
55
use rustc_hir::GenericArg;
66
use rustc_hir::def::{DefKind, PartialRes, Res};
77
use rustc_hir::def_id::DefId;
8-
use rustc_middle::span_bug;
8+
use rustc_middle::{span_bug, ty};
99
use rustc_session::parse::add_feature_diagnostics;
1010
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
1111
use smallvec::{SmallVec, smallvec};
@@ -590,14 +590,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
590590
/// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
591591
fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<DefId> {
592592
let lang_items = self.tcx.lang_items();
593-
if Some(def_id) == lang_items.fn_trait() {
594-
lang_items.async_fn_trait()
595-
} else if Some(def_id) == lang_items.fn_mut_trait() {
596-
lang_items.async_fn_mut_trait()
597-
} else if Some(def_id) == lang_items.fn_once_trait() {
598-
lang_items.async_fn_once_trait()
599-
} else {
600-
None
593+
match self.tcx.fn_trait_kind_from_def_id(def_id)? {
594+
ty::ClosureKind::Fn => lang_items.async_fn_trait(),
595+
ty::ClosureKind::FnMut => lang_items.async_fn_mut_trait(),
596+
ty::ClosureKind::FnOnce => lang_items.async_fn_once_trait(),
601597
}
602598
}
603599
}

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -1265,12 +1265,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
12651265
&& let CallKind::FnCall { fn_trait_id, self_ty } = kind
12661266
&& let ty::Param(_) = self_ty.kind()
12671267
&& ty == self_ty
1268-
&& [
1269-
self.infcx.tcx.lang_items().fn_once_trait(),
1270-
self.infcx.tcx.lang_items().fn_mut_trait(),
1271-
self.infcx.tcx.lang_items().fn_trait(),
1272-
]
1273-
.contains(&Some(fn_trait_id))
1268+
&& self.infcx.tcx.fn_trait_kind_from_def_id(fn_trait_id).is_some()
12741269
{
12751270
// Do not suggest `F: FnOnce() + Clone`.
12761271
false

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+26-34
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
33
use rustc_abi::ExternAbi;
44
use rustc_errors::DiagMessage;
5-
use rustc_hir::{self as hir};
6-
use rustc_middle::bug;
5+
use rustc_hir::{self as hir, LangItem};
76
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
87
use rustc_middle::ty::{self, Ty, TyCtxt};
98
use rustc_span::def_id::LocalDefId;
@@ -173,23 +172,22 @@ pub(crate) fn check_intrinsic_type(
173172
ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
174173
]);
175174
let mk_va_list_ty = |mutbl| {
176-
tcx.lang_items().va_list().map(|did| {
177-
let region = ty::Region::new_bound(
178-
tcx,
179-
ty::INNERMOST,
180-
ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
181-
);
182-
let env_region = ty::Region::new_bound(
183-
tcx,
184-
ty::INNERMOST,
185-
ty::BoundRegion {
186-
var: ty::BoundVar::from_u32(2),
187-
kind: ty::BoundRegionKind::ClosureEnv,
188-
},
189-
);
190-
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
191-
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
192-
})
175+
let did = tcx.require_lang_item(LangItem::VaList, Some(span));
176+
let region = ty::Region::new_bound(
177+
tcx,
178+
ty::INNERMOST,
179+
ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
180+
);
181+
let env_region = ty::Region::new_bound(
182+
tcx,
183+
ty::INNERMOST,
184+
ty::BoundRegion {
185+
var: ty::BoundVar::from_u32(2),
186+
kind: ty::BoundRegionKind::ClosureEnv,
187+
},
188+
);
189+
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
190+
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
193191
};
194192

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

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

556-
sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
557-
Some((va_list_ref_ty, va_list_ty)) => {
558-
let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
559-
(0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
560-
}
561-
None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
562-
},
553+
sym::va_copy => {
554+
let (va_list_ref_ty, va_list_ty) = mk_va_list_ty(hir::Mutability::Not);
555+
let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
556+
(0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
557+
}
563558

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

569561
sym::nontemporal_store => {
570562
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
750750
ObligationCause::misc(impl_span, checker.impl_def_id),
751751
param_env,
752752
nontrivial_field_ty,
753-
tcx.lang_items().pointer_like().unwrap(),
753+
tcx.require_lang_item(LangItem::PointerLike, Some(impl_span)),
754754
);
755755
// FIXME(dyn-star): We should regionck this implementation.
756756
if ocx.select_all_or_error().is_empty() {

compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub(crate) fn check_legal_trait_for_method_call(
3737
body_id: DefId,
3838
) -> Result<(), ErrorGuaranteed> {
3939
if tcx.is_lang_item(trait_id, LangItem::Drop)
40-
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
40+
&& !tcx.is_lang_item(body_id, LangItem::FallbackSurfaceDrop)
4141
{
4242
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
4343
errors::ExplicitDestructorCallSugg::Snippet {

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
925925

926926
let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
927927
if let ty::Adt(adt, _) = ty.kind()
928-
&& self.tcx().lang_items().get(hir::LangItem::RangeFull) == Some(adt.did())
928+
&& self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
929929
&& let hir::ExprKind::Struct(
930930
hir::QPath::LangItem(hir::LangItem::RangeFull, _),
931931
[],

compiler/rustc_hir_typeck/src/pat.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -1457,15 +1457,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14571457
_ => (None, None),
14581458
};
14591459

1460-
let ranges = &[
1461-
self.tcx.lang_items().range_struct(),
1462-
self.tcx.lang_items().range_from_struct(),
1463-
self.tcx.lang_items().range_to_struct(),
1464-
self.tcx.lang_items().range_full_struct(),
1465-
self.tcx.lang_items().range_inclusive_struct(),
1466-
self.tcx.lang_items().range_to_inclusive_struct(),
1467-
];
1468-
if type_def_id != None && ranges.contains(&type_def_id) {
1460+
let is_range = match type_def_id.and_then(|id| self.tcx.as_lang_item(id)) {
1461+
Some(
1462+
LangItem::Range
1463+
| LangItem::RangeFrom
1464+
| LangItem::RangeTo
1465+
| LangItem::RangeFull
1466+
| LangItem::RangeInclusiveStruct
1467+
| LangItem::RangeToInclusive,
1468+
) => true,
1469+
_ => false,
1470+
};
1471+
if is_range {
14691472
if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
14701473
let msg = "constants only support matching by type, \
14711474
if you meant to match against a range of values, \

compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ use std::cell::RefCell;
22
use std::ops::Deref;
33

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

compiler/rustc_lint/src/shadowed_into_iter.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_hir as hir;
1+
use rustc_hir::{self as hir, LangItem};
22
use rustc_middle::ty::{self, Ty};
33
use rustc_session::lint::FutureIncompatibilityReason;
44
use rustc_session::{declare_lint, impl_lint_pass};
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
8181
let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else {
8282
return;
8383
};
84-
if Some(method_def_id) != cx.tcx.lang_items().into_iter_fn() {
84+
if !cx.tcx.is_lang_item(method_def_id, LangItem::IntoIterIntoIter) {
8585
return;
8686
}
8787

compiler/rustc_middle/src/middle/lang_items.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ impl<'tcx> TyCtxt<'tcx> {
3535
/// returns a corresponding [`ty::ClosureKind`].
3636
/// For any other [`DefId`] return `None`.
3737
pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
38-
let items = self.lang_items();
39-
match Some(id) {
40-
x if x == items.fn_trait() => Some(ty::ClosureKind::Fn),
41-
x if x == items.fn_mut_trait() => Some(ty::ClosureKind::FnMut),
42-
x if x == items.fn_once_trait() => Some(ty::ClosureKind::FnOnce),
38+
match self.as_lang_item(id)? {
39+
LangItem::Fn => Some(ty::ClosureKind::Fn),
40+
LangItem::FnMut => Some(ty::ClosureKind::FnMut),
41+
LangItem::FnOnce => Some(ty::ClosureKind::FnOnce),
4342
_ => None,
4443
}
4544
}
@@ -48,11 +47,10 @@ impl<'tcx> TyCtxt<'tcx> {
4847
/// returns a corresponding [`ty::ClosureKind`].
4948
/// For any other [`DefId`] return `None`.
5049
pub fn async_fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
51-
let items = self.lang_items();
52-
match Some(id) {
53-
x if x == items.async_fn_trait() => Some(ty::ClosureKind::Fn),
54-
x if x == items.async_fn_mut_trait() => Some(ty::ClosureKind::FnMut),
55-
x if x == items.async_fn_once_trait() => Some(ty::ClosureKind::FnOnce),
50+
match self.as_lang_item(id)? {
51+
LangItem::AsyncFn => Some(ty::ClosureKind::Fn),
52+
LangItem::AsyncFnMut => Some(ty::ClosureKind::FnMut),
53+
LangItem::AsyncFnOnce => Some(ty::ClosureKind::FnOnce),
5654
_ => None,
5755
}
5856
}

compiler/rustc_middle/src/ty/sty.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1774,9 +1774,7 @@ impl<'tcx> Ty<'tcx> {
17741774
match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
17751775
Ok(metadata_ty) => metadata_ty,
17761776
Err(tail_ty) => {
1777-
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
1778-
bug!("No metadata_type lang item while looking at {self:?}")
1779-
};
1777+
let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
17801778
Ty::new_projection(tcx, metadata_def_id, [tail_ty])
17811779
}
17821780
}

compiler/rustc_mir_transform/src/check_call_recursion.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::ops::ControlFlow;
33
use rustc_data_structures::graph::iterate::{
44
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
55
};
6+
use rustc_hir::LangItem;
67
use rustc_hir::def::DefKind;
78
use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind};
89
use rustc_middle::ty::{self, GenericArg, GenericArgs, Instance, Ty, TyCtxt};
@@ -44,8 +45,7 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
4445
if let DefKind::AssocFn = tcx.def_kind(def_id)
4546
&& let Some(trait_ref) =
4647
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
47-
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
48-
&& drop_trait == trait_ref.instantiate_identity().def_id
48+
&& tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop)
4949
// avoid erroneous `Drop` impls from causing ICEs below
5050
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
5151
&& sig.inputs().skip_binder().len() == 1

compiler/rustc_monomorphize/src/partitioning.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ where
223223
match mono_item.instantiation_mode(cx.tcx) {
224224
InstantiationMode::GloballyShared { .. } => {}
225225
InstantiationMode::LocalCopy => {
226-
if Some(mono_item.def_id()) != cx.tcx.lang_items().start_fn() {
226+
if !cx.tcx.is_lang_item(mono_item.def_id(), LangItem::Start) {
227227
continue;
228228
}
229229
}

compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,7 @@ pub fn call_kind<'tcx>(
8181
}
8282
});
8383

84-
let fn_call = parent.and_then(|p| {
85-
lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
86-
});
84+
let fn_call = parent.filter(|&p| tcx.fn_trait_kind_from_def_id(p).is_some());
8785

8886
let operator = if !from_hir_call && let Some(p) = parent {
8987
lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
146146
&& leaf_trait_predicate.def_id() != root_pred.def_id()
147147
// The root trait is not `Unsize`, as to avoid talking about it in
148148
// `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
149-
&& Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
149+
&& !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize)
150150
{
151151
(
152152
self.resolve_vars_if_possible(
@@ -2274,10 +2274,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22742274
// auto-traits or fundamental traits that might not be exactly what
22752275
// the user might expect to be presented with. Instead this is
22762276
// useful for less general traits.
2277-
if peeled
2278-
&& !self.tcx.trait_is_auto(def_id)
2279-
&& !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
2280-
{
2277+
if peeled && !self.tcx.trait_is_auto(def_id) && self.tcx.as_lang_item(def_id).is_none() {
22812278
let impl_candidates = self.find_similar_impl_candidates(trait_pred);
22822279
self.report_similar_impl_candidates(
22832280
&impl_candidates,
@@ -3013,8 +3010,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
30133010
// This shouldn't be common unless manually implementing one of the
30143011
// traits manually, but don't make it more confusing when it does
30153012
// happen.
3016-
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
3017-
{
3013+
if !self.tcx.is_lang_item(expected_trait_ref.def_id, LangItem::Coroutine) && not_tupled {
30183014
return Ok(self.report_and_explain_type_error(
30193015
TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref),
30203016
obligation.param_env,

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -3844,12 +3844,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
38443844
);
38453845
if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
38463846
&& let ty::ClauseKind::Trait(pred) = clause
3847-
&& [
3848-
tcx.lang_items().fn_once_trait(),
3849-
tcx.lang_items().fn_mut_trait(),
3850-
tcx.lang_items().fn_trait(),
3851-
]
3852-
.contains(&Some(pred.def_id()))
3847+
&& tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some()
38533848
{
38543849
if let [stmt, ..] = block.stmts
38553850
&& let hir::StmtKind::Semi(value) = stmt.kind

compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::ops::ControlFlow;
22

3+
use rustc_hir::LangItem;
34
use rustc_infer::infer::InferCtxt;
45
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
56
use rustc_infer::traits::{
@@ -452,9 +453,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
452453
// We do this as a separate loop so that we do not choose to tell the user about some nested
453454
// goal before we encounter a `T: FnPtr` nested goal.
454455
for nested_goal in &nested_goals {
455-
if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait()
456-
&& let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
457-
&& poly_trait_pred.def_id() == fn_ptr_trait
456+
if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
457+
&& tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
458458
&& let Err(NoSolution) = nested_goal.result()
459459
{
460460
return ControlFlow::Break(self.obligation.clone());

0 commit comments

Comments
 (0)