spade_typeinference/
traits.rs

1use crate::{
2    equation::{TemplateTypeVarID, TypeVarID},
3    TypeState,
4};
5use itertools::Itertools;
6use serde::{Deserialize, Serialize};
7use spade_common::location_info::{Loc, WithLocation};
8use spade_hir::{ImplBlock, ImplTarget, TraitName};
9use std::collections::{BTreeSet, HashMap};
10
11#[derive(Clone, Serialize, Deserialize)]
12pub struct TraitImpl {
13    pub name: TraitName,
14    pub target_type_params: Vec<TemplateTypeVarID>,
15    pub trait_type_params: Vec<TemplateTypeVarID>,
16    pub impl_block: ImplBlock,
17}
18
19#[derive(Clone, Serialize, Deserialize)]
20pub struct TraitImplList {
21    pub inner: HashMap<ImplTarget, Vec<TraitImpl>>,
22}
23
24impl TraitImplList {
25    pub fn new() -> Self {
26        Self {
27            inner: HashMap::new(),
28        }
29    }
30}
31
32#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
33pub struct TraitReq {
34    pub name: TraitName,
35    pub type_params: Vec<TypeVarID>,
36}
37
38impl WithLocation for TraitReq {}
39
40impl TraitReq {
41    pub fn display(&self, type_state: &TypeState) -> String {
42        self.display_with_meta(false, type_state)
43    }
44
45    pub fn display_with_meta(&self, display_meta: bool, type_state: &TypeState) -> String {
46        if self.type_params.is_empty() {
47            format!("{}", self.name)
48        } else {
49            format!(
50                "{}<{}>",
51                self.name,
52                self.type_params
53                    .iter()
54                    .map(|t| format!("{}", t.display_with_meta(display_meta, type_state)))
55                    .join(", ")
56            )
57        }
58    }
59
60    pub fn debug_display(&self, type_state: &TypeState) -> String {
61        if self.type_params.is_empty() {
62            format!("{}", self.name)
63        } else {
64            format!(
65                "{}<{}>",
66                self.name,
67                self.type_params
68                    .iter()
69                    .map(|t| format!("{}", t.debug_resolve(type_state).0))
70                    .join(", ")
71            )
72        }
73    }
74}
75
76impl std::fmt::Debug for TraitReq {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        if self.type_params.is_empty() {
79            write!(f, "{}", self.name)
80        } else {
81            write!(
82                f,
83                "{}<{}>",
84                self.name,
85                self.type_params.iter().map(|t| format!("{t:?}")).join(", ")
86            )
87        }
88    }
89}
90
91#[derive(Clone, Debug, Serialize, Deserialize)]
92pub struct TraitList {
93    pub inner: Vec<Loc<TraitReq>>,
94}
95
96impl TraitList {
97    pub fn empty() -> Self {
98        Self { inner: vec![] }
99    }
100
101    pub fn from_vec(inner: Vec<Loc<TraitReq>>) -> Self {
102        Self { inner }
103    }
104
105    pub fn get_trait(&self, name: &TraitName) -> Option<&Loc<TraitReq>> {
106        self.inner.iter().find(|t| &t.name == name)
107    }
108
109    pub fn extend(self, other: Self) -> Self {
110        let merged = self
111            .inner
112            .into_iter()
113            .chain(other.inner.into_iter())
114            .collect::<BTreeSet<_>>()
115            .into_iter()
116            .collect_vec();
117
118        TraitList { inner: merged }
119    }
120
121    pub fn display_with_meta(&self, display_meta: bool, type_state: &TypeState) -> String {
122        self.inner
123            .iter()
124            .map(|t| t.inner.display_with_meta(display_meta, type_state))
125            .join(" + ")
126    }
127}
128
129// NOTE: The trait information is currently carried along with the type vars, but
130// the trait information should not be involved in comparisons
131impl PartialEq for TraitList {
132    fn eq(&self, _other: &Self) -> bool {
133        true
134    }
135}
136impl Eq for TraitList {}
137impl std::hash::Hash for TraitList {
138    fn hash<H: std::hash::Hasher>(&self, _state: &mut H) {}
139}
140impl PartialOrd for TraitList {
141    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
142        Some(self.cmp(other))
143    }
144}
145impl Ord for TraitList {
146    fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
147        std::cmp::Ordering::Equal
148    }
149}