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;
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 TraitReq {
39    pub fn display(&self, type_state: &TypeState) -> String {
40        self.display_with_meta(false, type_state)
41    }
42
43    pub fn display_with_meta(&self, display_meta: bool, type_state: &TypeState) -> String {
44        if self.type_params.is_empty() {
45            format!("{}", self.name)
46        } else {
47            format!(
48                "{}<{}>",
49                self.name,
50                self.type_params
51                    .iter()
52                    .map(|t| format!("{}", t.display_with_meta(display_meta, type_state)))
53                    .join(", ")
54            )
55        }
56    }
57
58    pub fn debug_display(&self, type_state: &TypeState) -> String {
59        if self.type_params.is_empty() {
60            format!("{}", self.name)
61        } else {
62            format!(
63                "{}<{}>",
64                self.name,
65                self.type_params
66                    .iter()
67                    .map(|t| format!("{}", t.debug_resolve(type_state).0))
68                    .join(", ")
69            )
70        }
71    }
72}
73
74impl std::fmt::Debug for TraitReq {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        if self.type_params.is_empty() {
77            write!(f, "{}", self.name)
78        } else {
79            write!(
80                f,
81                "{}<{}>",
82                self.name,
83                self.type_params.iter().map(|t| format!("{t:?}")).join(", ")
84            )
85        }
86    }
87}
88
89#[derive(Clone, Debug, Serialize, Deserialize)]
90pub struct TraitList {
91    pub inner: Vec<Loc<TraitReq>>,
92}
93
94impl TraitList {
95    pub fn empty() -> Self {
96        Self { inner: vec![] }
97    }
98
99    pub fn from_vec(inner: Vec<Loc<TraitReq>>) -> Self {
100        Self { inner }
101    }
102
103    pub fn get_trait(&self, name: &TraitName) -> Option<&Loc<TraitReq>> {
104        self.inner.iter().find(|t| &t.name == name)
105    }
106
107    pub fn extend(self, other: Self) -> Self {
108        let merged = self
109            .inner
110            .into_iter()
111            .chain(other.inner.into_iter())
112            .collect::<BTreeSet<_>>()
113            .into_iter()
114            .collect_vec();
115
116        TraitList { inner: merged }
117    }
118
119    pub fn display_with_meta(&self, display_meta: bool, type_state: &TypeState) -> String {
120        self.inner
121            .iter()
122            .map(|t| t.inner.display_with_meta(display_meta, type_state))
123            .join(" + ")
124    }
125}
126
127// NOTE: The trait information is currently carried along with the type vars, but
128// the trait information should not be involved in comparisons
129impl PartialEq for TraitList {
130    fn eq(&self, _other: &Self) -> bool {
131        true
132    }
133}
134impl Eq for TraitList {}
135impl std::hash::Hash for TraitList {
136    fn hash<H: std::hash::Hasher>(&self, _state: &mut H) {}
137}
138impl PartialOrd for TraitList {
139    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
140        Some(self.cmp(other))
141    }
142}
143impl Ord for TraitList {
144    fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
145        std::cmp::Ordering::Equal
146    }
147}