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
129impl 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}