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