Skip to content

Commit d1eb1a6

Browse files
committed
Auto merge of #140386 - oli-obk:match-on-lang-item-kind, r=<try>
Match on lang item kind instead of using an if/else chain Similar to how the new solver does this. Just noticed while I was adding a new entry to the chain 😆
2 parents 1b8ab72 + 03c05c9 commit d1eb1a6

File tree

2 files changed

+91
-85
lines changed

2 files changed

+91
-85
lines changed

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 86 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -66,71 +66,92 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
6666
let def_id = obligation.predicate.def_id();
6767
let tcx = self.tcx();
6868

69-
if tcx.is_lang_item(def_id, LangItem::Copy) {
70-
debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
71-
72-
// User-defined copy impls are permitted, but only for
73-
// structs and enums.
74-
self.assemble_candidates_from_impls(obligation, &mut candidates);
75-
76-
// For other types, we'll use the builtin rules.
77-
let copy_conditions = self.copy_clone_conditions(obligation);
78-
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
79-
} else if tcx.is_lang_item(def_id, LangItem::DiscriminantKind) {
80-
// `DiscriminantKind` is automatically implemented for every type.
81-
candidates.vec.push(BuiltinCandidate { has_nested: false });
82-
} else if tcx.is_lang_item(def_id, LangItem::PointeeTrait) {
83-
// `Pointee` is automatically implemented for every type.
84-
candidates.vec.push(BuiltinCandidate { has_nested: false });
85-
} else if tcx.is_lang_item(def_id, LangItem::Sized) {
86-
self.assemble_builtin_sized_candidate(obligation, &mut candidates);
87-
} else if tcx.is_lang_item(def_id, LangItem::Unsize) {
88-
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
89-
} else if tcx.is_lang_item(def_id, LangItem::Destruct) {
90-
self.assemble_const_destruct_candidates(obligation, &mut candidates);
91-
} else if tcx.is_lang_item(def_id, LangItem::TransmuteTrait) {
92-
// User-defined transmutability impls are permitted.
93-
self.assemble_candidates_from_impls(obligation, &mut candidates);
94-
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
95-
} else if tcx.is_lang_item(def_id, LangItem::Tuple) {
96-
self.assemble_candidate_for_tuple(obligation, &mut candidates);
97-
} else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
98-
self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
99-
} else if tcx.is_lang_item(def_id, LangItem::BikeshedGuaranteedNoDrop) {
100-
self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
101-
obligation,
102-
&mut candidates,
103-
);
104-
} else {
105-
if tcx.is_lang_item(def_id, LangItem::Clone) {
106-
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
107-
// for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
108-
// types have builtin support for `Clone`.
109-
let clone_conditions = self.copy_clone_conditions(obligation);
110-
self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
69+
let lang_item = tcx.as_lang_item(def_id);
70+
match lang_item {
71+
Some(LangItem::Copy | LangItem::Clone) => {
72+
debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
73+
74+
// User-defined copy impls are permitted, but only for
75+
// structs and enums.
76+
self.assemble_candidates_from_impls(obligation, &mut candidates);
77+
78+
// For other types, we'll use the builtin rules.
79+
let copy_conditions = self.copy_clone_conditions(obligation);
80+
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
11181
}
112-
113-
if tcx.is_lang_item(def_id, LangItem::Coroutine) {
114-
self.assemble_coroutine_candidates(obligation, &mut candidates);
115-
} else if tcx.is_lang_item(def_id, LangItem::Future) {
116-
self.assemble_future_candidates(obligation, &mut candidates);
117-
} else if tcx.is_lang_item(def_id, LangItem::Iterator) {
118-
self.assemble_iterator_candidates(obligation, &mut candidates);
119-
} else if tcx.is_lang_item(def_id, LangItem::FusedIterator) {
120-
self.assemble_fused_iterator_candidates(obligation, &mut candidates);
121-
} else if tcx.is_lang_item(def_id, LangItem::AsyncIterator) {
122-
self.assemble_async_iterator_candidates(obligation, &mut candidates);
123-
} else if tcx.is_lang_item(def_id, LangItem::AsyncFnKindHelper) {
124-
self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates);
82+
Some(LangItem::DiscriminantKind) => {
83+
// `DiscriminantKind` is automatically implemented for every type.
84+
candidates.vec.push(BuiltinCandidate { has_nested: false });
12585
}
86+
Some(LangItem::PointeeTrait) => {
87+
// `Pointee` is automatically implemented for every type.
88+
candidates.vec.push(BuiltinCandidate { has_nested: false });
89+
}
90+
Some(LangItem::Sized) => {
91+
self.assemble_builtin_sized_candidate(obligation, &mut candidates);
92+
}
93+
Some(LangItem::Unsize) => {
94+
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
95+
}
96+
Some(LangItem::Destruct) => {
97+
self.assemble_const_destruct_candidates(obligation, &mut candidates);
98+
}
99+
Some(LangItem::TransmuteTrait) => {
100+
// User-defined transmutability impls are permitted.
101+
self.assemble_candidates_from_impls(obligation, &mut candidates);
102+
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
103+
}
104+
Some(LangItem::Tuple) => {
105+
self.assemble_candidate_for_tuple(obligation, &mut candidates);
106+
}
107+
Some(LangItem::FnPtrTrait) => {
108+
self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
109+
}
110+
Some(LangItem::BikeshedGuaranteedNoDrop) => {
111+
self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
112+
obligation,
113+
&mut candidates,
114+
);
115+
}
116+
_ => {
117+
// We re-match here for traits that can have both builtin impls and user written impls.
118+
// After the builtin impls we need to also add user written impls, which we do not want to
119+
// do in general because just checking if there are any is expensive.
120+
match lang_item {
121+
Some(LangItem::Coroutine) => {
122+
self.assemble_coroutine_candidates(obligation, &mut candidates);
123+
}
124+
Some(LangItem::Future) => {
125+
self.assemble_future_candidates(obligation, &mut candidates);
126+
}
127+
Some(LangItem::Iterator) => {
128+
self.assemble_iterator_candidates(obligation, &mut candidates);
129+
}
130+
Some(LangItem::FusedIterator) => {
131+
self.assemble_fused_iterator_candidates(obligation, &mut candidates);
132+
}
133+
Some(LangItem::AsyncIterator) => {
134+
self.assemble_async_iterator_candidates(obligation, &mut candidates);
135+
}
136+
Some(LangItem::AsyncFnKindHelper) => {
137+
self.assemble_async_fn_kind_helper_candidates(
138+
obligation,
139+
&mut candidates,
140+
);
141+
}
142+
Some(LangItem::AsyncFn | LangItem::AsyncFnMut | LangItem::AsyncFnOnce) => {
143+
self.assemble_async_closure_candidates(obligation, &mut candidates);
144+
}
145+
Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
146+
self.assemble_closure_candidates(obligation, &mut candidates);
147+
self.assemble_fn_pointer_candidates(obligation, &mut candidates);
148+
}
149+
_ => {}
150+
}
126151

127-
// FIXME: Put these into `else if` blocks above, since they're built-in.
128-
self.assemble_closure_candidates(obligation, &mut candidates);
129-
self.assemble_async_closure_candidates(obligation, &mut candidates);
130-
self.assemble_fn_pointer_candidates(obligation, &mut candidates);
131-
132-
self.assemble_candidates_from_impls(obligation, &mut candidates);
133-
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
152+
self.assemble_candidates_from_impls(obligation, &mut candidates);
153+
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
154+
}
134155
}
135156

136157
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
@@ -361,9 +382,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
361382
obligation: &PolyTraitObligation<'tcx>,
362383
candidates: &mut SelectionCandidateSet<'tcx>,
363384
) {
364-
let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
365-
return;
366-
};
385+
let kind = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
367386

368387
// Okay to skip binder because the args on closure types never
369388
// touch bound regions, they just capture the in-scope
@@ -425,11 +444,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
425444
obligation: &PolyTraitObligation<'tcx>,
426445
candidates: &mut SelectionCandidateSet<'tcx>,
427446
) {
428-
let Some(goal_kind) =
429-
self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id())
430-
else {
431-
return;
432-
};
447+
let goal_kind =
448+
self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
433449

434450
match *obligation.self_ty().skip_binder().kind() {
435451
ty::CoroutineClosure(_, args) => {
@@ -502,11 +518,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
502518
obligation: &PolyTraitObligation<'tcx>,
503519
candidates: &mut SelectionCandidateSet<'tcx>,
504520
) {
505-
// We provide impl of all fn traits for fn pointers.
506-
if !self.tcx().is_fn_trait(obligation.predicate.def_id()) {
507-
return;
508-
}
509-
510521
// Keep this function in sync with extract_tupled_inputs_and_output_from_callable
511522
// until the old solver (and thus this function) is removed.
512523

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
252252
let tcx = self.tcx();
253253
let obligations = if has_nested {
254254
let trait_def = obligation.predicate.def_id();
255-
let conditions = if tcx.is_lang_item(trait_def, LangItem::Sized) {
256-
self.sized_conditions(obligation)
257-
} else if tcx.is_lang_item(trait_def, LangItem::Copy) {
258-
self.copy_clone_conditions(obligation)
259-
} else if tcx.is_lang_item(trait_def, LangItem::Clone) {
260-
self.copy_clone_conditions(obligation)
261-
} else if tcx.is_lang_item(trait_def, LangItem::FusedIterator) {
262-
self.fused_iterator_conditions(obligation)
263-
} else {
264-
bug!("unexpected builtin trait {:?}", trait_def)
255+
let conditions = match tcx.as_lang_item(trait_def) {
256+
Some(LangItem::Sized) => self.sized_conditions(obligation),
257+
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation),
258+
Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation),
259+
other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"),
265260
};
266261
let BuiltinImplConditions::Where(types) = conditions else {
267262
bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);

0 commit comments

Comments
 (0)