Skip to content

Commit 356f2d0

Browse files
committed
Auto merge of #140386 - oli-obk:match-on-lang-item-kind, r=compiler-errors
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 c43786c + 03c05c9 commit 356f2d0

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
@@ -65,71 +65,92 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
6565
let def_id = obligation.predicate.def_id();
6666
let tcx = self.tcx();
6767

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

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

135156
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
@@ -360,9 +381,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
360381
obligation: &PolyTraitObligation<'tcx>,
361382
candidates: &mut SelectionCandidateSet<'tcx>,
362383
) {
363-
let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
364-
return;
365-
};
384+
let kind = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
366385

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

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

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

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

0 commit comments

Comments
 (0)