1use crate::{Ident, Path, Type};
6use joule_common::Span;
7
8#[derive(Debug, Clone, PartialEq)]
10pub struct GenericParams {
11 pub params: Vec<GenericParam>,
12 pub span: Span,
13}
14
15impl GenericParams {
16 pub const fn new(params: Vec<GenericParam>, span: Span) -> Self {
17 Self { params, span }
18 }
19
20 pub const fn empty() -> Self {
21 Self {
22 params: Vec::new(),
23 span: Span::dummy(),
24 }
25 }
26
27 pub const fn is_empty(&self) -> bool {
28 self.params.is_empty()
29 }
30
31 pub const fn len(&self) -> usize {
32 self.params.len()
33 }
34}
35
36impl Default for GenericParams {
37 fn default() -> Self {
38 Self::empty()
39 }
40}
41
42#[derive(Debug, Clone, PartialEq)]
44pub struct GenericParam {
45 pub name: Ident,
46 pub bounds: Vec<TypeBound>,
47 pub default: Option<Box<Type>>,
48 pub span: Span,
49}
50
51impl GenericParam {
52 pub const fn new(name: Ident, span: Span) -> Self {
53 Self {
54 name,
55 bounds: Vec::new(),
56 default: None,
57 span,
58 }
59 }
60
61 pub const fn with_bounds(name: Ident, bounds: Vec<TypeBound>, span: Span) -> Self {
62 Self {
63 name,
64 bounds,
65 default: None,
66 span,
67 }
68 }
69
70 pub fn with_default(name: Ident, bounds: Vec<TypeBound>, default: Type, span: Span) -> Self {
71 Self {
72 name,
73 bounds,
74 default: Some(Box::new(default)),
75 span,
76 }
77 }
78}
79
80#[derive(Debug, Clone, PartialEq)]
82pub struct TypeBound {
83 pub trait_path: Path,
84 pub generic_args: Option<GenericArgs>,
85 pub span: Span,
86}
87
88impl TypeBound {
89 pub const fn new(trait_path: Path, span: Span) -> Self {
90 Self {
91 trait_path,
92 generic_args: None,
93 span,
94 }
95 }
96
97 pub const fn with_args(trait_path: Path, generic_args: GenericArgs, span: Span) -> Self {
98 Self {
99 trait_path,
100 generic_args: Some(generic_args),
101 span,
102 }
103 }
104}
105
106#[derive(Debug, Clone, PartialEq)]
108pub struct GenericArgs {
109 pub args: Vec<GenericArg>,
110 pub span: Span,
111}
112
113impl GenericArgs {
114 pub const fn new(args: Vec<GenericArg>, span: Span) -> Self {
115 Self { args, span }
116 }
117
118 pub const fn empty() -> Self {
119 Self {
120 args: Vec::new(),
121 span: Span::dummy(),
122 }
123 }
124
125 pub const fn is_empty(&self) -> bool {
126 self.args.is_empty()
127 }
128
129 pub const fn len(&self) -> usize {
130 self.args.len()
131 }
132}
133
134impl Default for GenericArgs {
135 fn default() -> Self {
136 Self::empty()
137 }
138}
139
140#[derive(Debug, Clone, PartialEq)]
142pub enum GenericArg {
143 Type(Type),
145 Const(Box<crate::Expr>),
147 Binding { name: Ident, ty: Type },
149}
150
151impl GenericArg {
152 pub fn span(&self) -> Span {
153 match self {
154 Self::Type(ty) => ty.span(),
155 Self::Const(expr) => expr.span(),
156 Self::Binding { name, ty } => name.span.to(ty.span()),
157 }
158 }
159}
160
161#[derive(Debug, Clone, PartialEq)]
163pub struct WhereClause {
164 pub predicates: Vec<WherePredicate>,
165 pub span: Span,
166}
167
168impl WhereClause {
169 pub const fn new(predicates: Vec<WherePredicate>, span: Span) -> Self {
170 Self { predicates, span }
171 }
172
173 pub const fn empty() -> Self {
174 Self {
175 predicates: Vec::new(),
176 span: Span::dummy(),
177 }
178 }
179
180 pub const fn is_empty(&self) -> bool {
181 self.predicates.is_empty()
182 }
183}
184
185impl Default for WhereClause {
186 fn default() -> Self {
187 Self::empty()
188 }
189}
190
191#[derive(Debug, Clone, PartialEq)]
193pub struct WherePredicate {
194 pub ty: Type,
195 pub bounds: Vec<TypeBound>,
196 pub span: Span,
197}
198
199impl WherePredicate {
200 pub const fn new(ty: Type, bounds: Vec<TypeBound>, span: Span) -> Self {
201 Self { ty, bounds, span }
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208 use joule_common::Symbol;
209
210 fn make_ident(name: &str) -> Ident {
211 Ident::new(Symbol::intern(name), Span::dummy())
212 }
213
214 fn make_path(name: &str) -> Path {
215 Path {
216 segments: vec![make_ident(name)],
217 span: Span::dummy(),
218 }
219 }
220
221 #[test]
222 fn test_empty_generic_params() {
223 let params = GenericParams::empty();
224 assert!(params.is_empty());
225 assert_eq!(params.len(), 0);
226 }
227
228 #[test]
229 fn test_generic_param_creation() {
230 let name = make_ident("T");
231 let param = GenericParam::new(name.clone(), Span::dummy());
232 assert_eq!(param.name, name);
233 assert!(param.bounds.is_empty());
234 assert!(param.default.is_none());
235 }
236
237 #[test]
238 fn test_generic_param_with_bounds() {
239 let name = make_ident("T");
240 let bound = TypeBound::new(make_path("Clone"), Span::dummy());
241 let param = GenericParam::with_bounds(name.clone(), vec![bound], Span::dummy());
242 assert_eq!(param.name, name);
243 assert_eq!(param.bounds.len(), 1);
244 }
245
246 #[test]
247 fn test_generic_args() {
248 let ty = Type::Path {
249 path: make_path("i32"),
250 generics: None,
251 };
252 let args = GenericArgs::new(vec![GenericArg::Type(ty)], Span::dummy());
253 assert_eq!(args.len(), 1);
254 assert!(!args.is_empty());
255 }
256
257 #[test]
258 fn test_where_clause() {
259 let ty = Type::Path {
260 path: make_path("T"),
261 generics: None,
262 };
263 let bound = TypeBound::new(make_path("Clone"), Span::dummy());
264 let pred = WherePredicate::new(ty, vec![bound], Span::dummy());
265 let clause = WhereClause::new(vec![pred], Span::dummy());
266 assert!(!clause.is_empty());
267 }
268}