]> git.proxmox.com Git - rustc.git/blob - vendor/chalk-ir/src/could_match.rs
New upstream version 1.45.0+dfsg1
[rustc.git] / vendor / chalk-ir / src / could_match.rs
1 use crate::interner::HasInterner;
2 use crate::zip::{Zip, Zipper};
3 use crate::*;
4
5 /// A fast check to see whether two things could ever possibly match.
6 pub trait CouldMatch<T: ?Sized + HasInterner> {
7 fn could_match(&self, interner: &T::Interner, other: &T) -> bool;
8 }
9
10 #[allow(unreachable_code, unused_variables)]
11 impl<T, I> CouldMatch<T> for T
12 where
13 T: Zip<I> + ?Sized + HasInterner<Interner = I>,
14 I: Interner,
15 {
16 fn could_match(&self, interner: &I, other: &T) -> bool {
17 return Zip::zip_with(&mut MatchZipper { interner }, self, other).is_ok();
18
19 struct MatchZipper<'i, I> {
20 interner: &'i I,
21 };
22
23 impl<'i, I: Interner> Zipper<'i, I> for MatchZipper<'i, I> {
24 fn zip_tys(&mut self, a: &Ty<I>, b: &Ty<I>) -> Fallible<()> {
25 let interner = self.interner;
26 let could_match = match (a.data(interner), b.data(interner)) {
27 (&TyData::Apply(ref a), &TyData::Apply(ref b)) => {
28 let names_could_match = a.name == b.name;
29
30 names_could_match
31 && a.substitution
32 .iter(interner)
33 .zip(b.substitution.iter(interner))
34 .all(|(p_a, p_b)| p_a.could_match(interner, &p_b))
35 }
36
37 _ => true,
38 };
39
40 if could_match {
41 Ok(())
42 } else {
43 Err(NoSolution)
44 }
45 }
46
47 fn zip_lifetimes(&mut self, _: &Lifetime<I>, _: &Lifetime<I>) -> Fallible<()> {
48 Ok(())
49 }
50
51 fn zip_binders<T>(&mut self, a: &Binders<T>, b: &Binders<T>) -> Fallible<()>
52 where
53 T: HasInterner + Zip<I>,
54 {
55 Zip::zip_with(self, &a.value, &b.value)
56 }
57
58 fn interner(&self) -> &'i I {
59 self.interner
60 }
61 }
62 }
63 }
64
65 impl<I: Interner> CouldMatch<DomainGoal<I>> for ProgramClauseData<I> {
66 fn could_match(&self, interner: &I, other: &DomainGoal<I>) -> bool {
67 match self {
68 ProgramClauseData::Implies(implication) => {
69 implication.consequence.could_match(interner, other)
70 }
71
72 ProgramClauseData::ForAll(clause) => {
73 clause.value.consequence.could_match(interner, other)
74 }
75 }
76 }
77 }
78
79 impl<I: Interner> CouldMatch<DomainGoal<I>> for ProgramClause<I> {
80 fn could_match(&self, interner: &I, other: &DomainGoal<I>) -> bool {
81 self.data(interner).could_match(interner, other)
82 }
83 }