spade_typeinference/
traits.rs

1use 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
128// NOTE: The trait information is currently carried along with the type vars, but
129// the trait information should not be involved in comparisons
130impl 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}