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