1 //! Fast matching check for zippable values.
3 use crate::interner
::HasInterner
;
4 use crate::zip
::{Zip, Zipper}
;
7 /// A fast check to see whether two things could ever possibly match.
8 pub trait CouldMatch
<T
: ?Sized
+ HasInterner
> {
9 /// Checks whether `self` and `other` could possibly match.
12 interner
: &T
::Interner
,
13 db
: &dyn UnificationDatabase
<T
::Interner
>,
18 #[allow(unreachable_code, unused_variables)]
19 impl<T
, I
> CouldMatch
<T
> for T
21 T
: Zip
<I
> + ?Sized
+ HasInterner
<Interner
= I
>,
24 fn could_match(&self, interner
: &I
, db
: &dyn UnificationDatabase
<I
>, other
: &T
) -> bool
{
26 &mut MatchZipper { interner, db }
,
33 struct MatchZipper
<'i
, I
> {
35 db
: &'i
dyn UnificationDatabase
<I
>,
38 impl<'i
, I
: Interner
> Zipper
<'i
, I
> for MatchZipper
<'i
, I
> {
39 fn zip_tys(&mut self, variance
: Variance
, a
: &Ty
<I
>, b
: &Ty
<I
>) -> Fallible
<()> {
40 let interner
= self.interner
;
41 let matches
= |a
: &Substitution
<I
>, b
: &Substitution
<I
>| {
43 .zip(b
.iter(interner
))
44 .all(|(p_a
, p_b
)| p_a
.could_match(interner
, self.db
, &p_b
))
46 let could_match
= match (a
.kind(interner
), b
.kind(interner
)) {
47 (TyKind
::Adt(id_a
, substitution_a
), TyKind
::Adt(id_b
, substitution_b
)) => {
52 Some(self.unification_database().adt_variance(*id_a
)),
53 substitution_a
.as_slice(interner
),
54 substitution_b
.as_slice(interner
),
59 TyKind
::AssociatedType(assoc_ty_a
, substitution_a
),
60 TyKind
::AssociatedType(assoc_ty_b
, substitution_b
),
61 ) => assoc_ty_a
== assoc_ty_b
&& matches(substitution_a
, substitution_b
),
62 (TyKind
::Scalar(scalar_a
), TyKind
::Scalar(scalar_b
)) => scalar_a
== scalar_b
,
63 (TyKind
::Str
, TyKind
::Str
) => true,
65 TyKind
::Tuple(arity_a
, substitution_a
),
66 TyKind
::Tuple(arity_b
, substitution_b
),
67 ) => arity_a
== arity_b
&& matches(substitution_a
, substitution_b
),
69 TyKind
::OpaqueType(opaque_ty_a
, substitution_a
),
70 TyKind
::OpaqueType(opaque_ty_b
, substitution_b
),
71 ) => opaque_ty_a
== opaque_ty_b
&& matches(substitution_a
, substitution_b
),
72 (TyKind
::Slice(ty_a
), TyKind
::Slice(ty_b
)) => {
73 ty_a
.could_match(interner
, self.db
, ty_b
)
76 TyKind
::FnDef(fn_def_a
, substitution_a
),
77 TyKind
::FnDef(fn_def_b
, substitution_b
),
83 Some(self.unification_database().fn_def_variance(*fn_def_a
)),
84 substitution_a
.as_slice(interner
),
85 substitution_b
.as_slice(interner
),
90 TyKind
::Ref(mutability_a
, lifetime_a
, ty_a
),
91 TyKind
::Ref(mutability_b
, lifetime_b
, ty_b
),
93 mutability_a
== mutability_b
94 && lifetime_a
.could_match(interner
, self.db
, &lifetime_b
)
95 && ty_a
.could_match(interner
, self.db
, &ty_b
)
97 (TyKind
::Raw(mutability_a
, ty_a
), TyKind
::Raw(mutability_b
, ty_b
)) => {
98 mutability_a
== mutability_b
&& ty_a
.could_match(interner
, self.db
, &ty_b
)
100 (TyKind
::Never
, TyKind
::Never
) => true,
101 (TyKind
::Array(ty_a
, const_a
), TyKind
::Array(ty_b
, const_b
)) => {
102 ty_a
.could_match(interner
, self.db
, ty_b
)
103 && const_a
.could_match(interner
, self.db
, const_b
)
106 TyKind
::Closure(id_a
, substitution_a
),
107 TyKind
::Closure(id_b
, substitution_b
),
108 ) => id_a
== id_b
&& matches(substitution_a
, substitution_b
),
110 TyKind
::Generator(generator_a
, substitution_a
),
111 TyKind
::Generator(generator_b
, substitution_b
),
113 generator_a
== generator_b
118 substitution_a
.as_slice(interner
),
119 substitution_b
.as_slice(interner
),
124 TyKind
::GeneratorWitness(generator_a
, substitution_a
),
125 TyKind
::GeneratorWitness(generator_b
, substitution_b
),
127 generator_a
== generator_b
132 substitution_a
.as_slice(interner
),
133 substitution_b
.as_slice(interner
),
137 (TyKind
::Foreign(foreign_ty_a
), TyKind
::Foreign(foreign_ty_b
)) => {
138 foreign_ty_a
== foreign_ty_b
140 (TyKind
::Error
, TyKind
::Error
) => true,
177 T
: HasInterner
+ Zip
<I
>,
179 Zip
::zip_with(self, variance
, &a
.value
, &b
.value
)
182 fn interner(&self) -> &'i I
{
186 fn unification_database(&self) -> &dyn UnificationDatabase
<I
> {
193 impl<I
: Interner
> CouldMatch
<DomainGoal
<I
>> for ProgramClauseData
<I
> {
197 db
: &dyn UnificationDatabase
<I
>,
198 other
: &DomainGoal
<I
>,
200 self.0.value
.consequence
.could_match(interner
, db
, other
)
204 impl<I
: Interner
> CouldMatch
<DomainGoal
<I
>> for ProgramClause
<I
> {
208 db
: &dyn UnificationDatabase
<I
>,
209 other
: &DomainGoal
<I
>,
211 self.data(interner
).could_match(interner
, db
, other
)