1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
use super::{builder::ClauseBuilder, generalize};
use crate::{CanonicalVarKinds, Interner, RustIrDatabase, TraitRef, WellKnownTrait};
use chalk_ir::{Floundered, Substitution, Ty};
mod clone;
mod copy;
mod discriminant_kind;
mod fn_family;
mod generator;
mod sized;
mod tuple;
mod unsize;
/// For well known traits we have special hard-coded impls, either as an
/// optimization or to enforce special rules for correctness.
pub fn add_builtin_program_clauses<I: Interner>(
db: &dyn RustIrDatabase<I>,
builder: &mut ClauseBuilder<'_, I>,
well_known: WellKnownTrait,
trait_ref: TraitRef<I>,
binders: &CanonicalVarKinds<I>,
) -> Result<(), Floundered> {
// If `trait_ref` contains bound vars, we want to universally quantify them.
// `Generalize` collects them for us.
let generalized = generalize::Generalize::apply(db.interner(), trait_ref);
builder.push_binders(generalized, |builder, trait_ref| {
let self_ty = trait_ref.self_type_parameter(db.interner());
let ty = self_ty.kind(db.interner()).clone();
match well_known {
// Built-in traits are non-enumerable.
_ if self_ty.is_general_var(db.interner(), binders) => return Err(Floundered),
WellKnownTrait::Sized => {
sized::add_sized_program_clauses(db, builder, trait_ref, ty, binders)?;
}
WellKnownTrait::Copy => {
copy::add_copy_program_clauses(db, builder, trait_ref, ty, binders)?;
}
WellKnownTrait::Clone => {
clone::add_clone_program_clauses(db, builder, trait_ref, ty, binders)?;
}
WellKnownTrait::FnOnce | WellKnownTrait::FnMut | WellKnownTrait::Fn => {
fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty);
}
WellKnownTrait::Unsize => {
unsize::add_unsize_program_clauses(db, builder, trait_ref, ty)
}
// DiscriminantKind is automatically implemented for all types
WellKnownTrait::DiscriminantKind => builder.push_fact(trait_ref),
WellKnownTrait::Generator => {
generator::add_generator_program_clauses(db, builder, self_ty)?;
}
WellKnownTrait::Tuple => {
tuple::add_tuple_program_clauses(db, builder, self_ty)?;
}
// There are no builtin impls provided for the following traits:
WellKnownTrait::Unpin
| WellKnownTrait::Drop
| WellKnownTrait::CoerceUnsized
| WellKnownTrait::DispatchFromDyn => (),
}
Ok(())
})
}
/// Like `add_builtin_program_clauses`, but for `DomainGoal::Normalize` involving
/// a projection (e.g. `<fn(u8) as FnOnce<(u8,)>>::Output`)
pub fn add_builtin_assoc_program_clauses<I: Interner>(
db: &dyn RustIrDatabase<I>,
builder: &mut ClauseBuilder<'_, I>,
well_known: WellKnownTrait,
self_ty: Ty<I>,
) -> Result<(), Floundered> {
match well_known {
WellKnownTrait::FnOnce => {
// If `self_ty` contains bound vars, we want to universally quantify them.
// `Generalize` collects them for us.
let generalized = generalize::Generalize::apply(db.interner(), self_ty);
builder.push_binders(generalized, |builder, self_ty| {
fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty);
Ok(())
})
}
WellKnownTrait::DiscriminantKind => {
discriminant_kind::add_discriminant_clauses(db, builder, self_ty)
}
WellKnownTrait::Generator => {
let generalized = generalize::Generalize::apply(db.interner(), self_ty);
builder.push_binders(generalized, |builder, self_ty| {
generator::add_generator_program_clauses(db, builder, self_ty)
})
}
_ => Ok(()),
}
}
/// Given a trait ref `T0: Trait` and a list of types `U0..Un`, pushes a clause of the form
/// `Implemented(T0: Trait) :- Implemented(U0: Trait) .. Implemented(Un: Trait)`
pub fn needs_impl_for_tys<I: Interner>(
db: &dyn RustIrDatabase<I>,
builder: &mut ClauseBuilder<'_, I>,
trait_ref: TraitRef<I>,
tys: impl Iterator<Item = Ty<I>>,
) {
let trait_id = trait_ref.trait_id;
// The trait must take one parameter (a type)
debug_assert_eq!(db.trait_datum(trait_id).binders.len(db.interner()), 1,);
builder.push_clause(
trait_ref,
tys.map(|ty| TraitRef {
trait_id,
substitution: Substitution::from1(db.interner(), ty),
}),
);
}
|