solscript_typeck/
types.rs

1//! Core type system types for SolScript (Solidity-style)
2
3use indexmap::IndexMap;
4use smol_str::SmolStr;
5use std::fmt;
6
7/// A unique identifier for a type
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct TypeId(pub u32);
10
11/// The core type representation
12#[derive(Debug, Clone, PartialEq)]
13pub enum Type {
14    /// Primitive types
15    Primitive(PrimitiveType),
16    /// Unit type ()
17    Unit,
18    /// Never type (for functions that don't return)
19    Never,
20    /// A named type (struct, enum, contract, interface, etc.)
21    Named(NamedType),
22    /// Fixed-size array type `T[N]`
23    Array(Box<Type>, u64),
24    /// Dynamic array type T[]
25    DynamicArray(Box<Type>),
26    /// Tuple type (T1, T2, ...)
27    Tuple(Vec<Type>),
28    /// Mapping type mapping(K => V)
29    Mapping(Box<Type>, Box<Type>),
30    /// Function type function(A, B) returns (C)
31    Function(FunctionType),
32    /// A type variable (for inference)
33    Var(TypeVar),
34    /// An error type (used during type checking when errors occur)
35    Error,
36}
37
38impl Type {
39    /// Check if this is a numeric type
40    pub fn is_numeric(&self) -> bool {
41        matches!(self, Type::Primitive(p) if p.is_numeric())
42    }
43
44    /// Check if this is an integer type
45    pub fn is_integer(&self) -> bool {
46        matches!(self, Type::Primitive(p) if p.is_integer())
47    }
48
49    /// Check if this is a signed integer type
50    pub fn is_signed(&self) -> bool {
51        matches!(self, Type::Primitive(p) if p.is_signed())
52    }
53
54    /// Check if this is a boolean type
55    pub fn is_bool(&self) -> bool {
56        matches!(self, Type::Primitive(PrimitiveType::Bool))
57    }
58
59    /// Check if this is an address type
60    pub fn is_address(&self) -> bool {
61        matches!(self, Type::Primitive(PrimitiveType::Address))
62    }
63
64    /// Check if this type contains any type variables
65    pub fn has_type_vars(&self) -> bool {
66        match self {
67            Type::Var(_) => true,
68            Type::Array(t, _) | Type::DynamicArray(t) => t.has_type_vars(),
69            Type::Tuple(ts) => ts.iter().any(|t| t.has_type_vars()),
70            Type::Mapping(k, v) => k.has_type_vars() || v.has_type_vars(),
71            Type::Function(f) => {
72                f.params.iter().any(|t| t.has_type_vars()) || f.return_type.has_type_vars()
73            }
74            Type::Named(n) => n.type_args.iter().any(|t| t.has_type_vars()),
75            _ => false,
76        }
77    }
78}
79
80impl fmt::Display for Type {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        match self {
83            Type::Primitive(p) => write!(f, "{}", p),
84            Type::Unit => write!(f, "()"),
85            Type::Never => write!(f, "!"),
86            Type::Named(n) => write!(f, "{}", n),
87            Type::Array(t, n) => write!(f, "{}[{}]", t, n),
88            Type::DynamicArray(t) => write!(f, "{}[]", t),
89            Type::Tuple(ts) => {
90                write!(f, "(")?;
91                for (i, t) in ts.iter().enumerate() {
92                    if i > 0 {
93                        write!(f, ", ")?;
94                    }
95                    write!(f, "{}", t)?;
96                }
97                write!(f, ")")
98            }
99            Type::Mapping(k, v) => write!(f, "mapping({} => {})", k, v),
100            Type::Function(ft) => write!(f, "{}", ft),
101            Type::Var(v) => write!(f, "{}", v),
102            Type::Error => write!(f, "<error>"),
103        }
104    }
105}
106
107/// Primitive types (Solidity-style)
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
109pub enum PrimitiveType {
110    // Unsigned integers
111    Uint8,
112    Uint16,
113    Uint24,
114    Uint32,
115    Uint40,
116    Uint48,
117    Uint56,
118    Uint64,
119    Uint72,
120    Uint80,
121    Uint88,
122    Uint96,
123    Uint104,
124    Uint112,
125    Uint120,
126    Uint128,
127    Uint136,
128    Uint144,
129    Uint152,
130    Uint160,
131    Uint168,
132    Uint176,
133    Uint184,
134    Uint192,
135    Uint200,
136    Uint208,
137    Uint216,
138    Uint224,
139    Uint232,
140    Uint240,
141    Uint248,
142    Uint256,
143    // Signed integers
144    Int8,
145    Int16,
146    Int24,
147    Int32,
148    Int40,
149    Int48,
150    Int56,
151    Int64,
152    Int72,
153    Int80,
154    Int88,
155    Int96,
156    Int104,
157    Int112,
158    Int120,
159    Int128,
160    Int136,
161    Int144,
162    Int152,
163    Int160,
164    Int168,
165    Int176,
166    Int184,
167    Int192,
168    Int200,
169    Int208,
170    Int216,
171    Int224,
172    Int232,
173    Int240,
174    Int248,
175    Int256,
176    // Other primitives
177    Bool,
178    Address,
179    Signer, // Solana-specific: represents a required signer account
180    String,
181    Bytes,
182    Bytes1,
183    Bytes2,
184    Bytes3,
185    Bytes4,
186    Bytes5,
187    Bytes6,
188    Bytes7,
189    Bytes8,
190    Bytes9,
191    Bytes10,
192    Bytes11,
193    Bytes12,
194    Bytes13,
195    Bytes14,
196    Bytes15,
197    Bytes16,
198    Bytes17,
199    Bytes18,
200    Bytes19,
201    Bytes20,
202    Bytes21,
203    Bytes22,
204    Bytes23,
205    Bytes24,
206    Bytes25,
207    Bytes26,
208    Bytes27,
209    Bytes28,
210    Bytes29,
211    Bytes30,
212    Bytes31,
213    Bytes32,
214}
215
216impl PrimitiveType {
217    pub fn is_numeric(&self) -> bool {
218        self.is_integer()
219    }
220
221    pub fn is_integer(&self) -> bool {
222        matches!(
223            self,
224            PrimitiveType::Uint8
225                | PrimitiveType::Uint16
226                | PrimitiveType::Uint24
227                | PrimitiveType::Uint32
228                | PrimitiveType::Uint40
229                | PrimitiveType::Uint48
230                | PrimitiveType::Uint56
231                | PrimitiveType::Uint64
232                | PrimitiveType::Uint72
233                | PrimitiveType::Uint80
234                | PrimitiveType::Uint88
235                | PrimitiveType::Uint96
236                | PrimitiveType::Uint104
237                | PrimitiveType::Uint112
238                | PrimitiveType::Uint120
239                | PrimitiveType::Uint128
240                | PrimitiveType::Uint136
241                | PrimitiveType::Uint144
242                | PrimitiveType::Uint152
243                | PrimitiveType::Uint160
244                | PrimitiveType::Uint168
245                | PrimitiveType::Uint176
246                | PrimitiveType::Uint184
247                | PrimitiveType::Uint192
248                | PrimitiveType::Uint200
249                | PrimitiveType::Uint208
250                | PrimitiveType::Uint216
251                | PrimitiveType::Uint224
252                | PrimitiveType::Uint232
253                | PrimitiveType::Uint240
254                | PrimitiveType::Uint248
255                | PrimitiveType::Uint256
256                | PrimitiveType::Int8
257                | PrimitiveType::Int16
258                | PrimitiveType::Int24
259                | PrimitiveType::Int32
260                | PrimitiveType::Int40
261                | PrimitiveType::Int48
262                | PrimitiveType::Int56
263                | PrimitiveType::Int64
264                | PrimitiveType::Int72
265                | PrimitiveType::Int80
266                | PrimitiveType::Int88
267                | PrimitiveType::Int96
268                | PrimitiveType::Int104
269                | PrimitiveType::Int112
270                | PrimitiveType::Int120
271                | PrimitiveType::Int128
272                | PrimitiveType::Int136
273                | PrimitiveType::Int144
274                | PrimitiveType::Int152
275                | PrimitiveType::Int160
276                | PrimitiveType::Int168
277                | PrimitiveType::Int176
278                | PrimitiveType::Int184
279                | PrimitiveType::Int192
280                | PrimitiveType::Int200
281                | PrimitiveType::Int208
282                | PrimitiveType::Int216
283                | PrimitiveType::Int224
284                | PrimitiveType::Int232
285                | PrimitiveType::Int240
286                | PrimitiveType::Int248
287                | PrimitiveType::Int256
288        )
289    }
290
291    pub fn is_signed(&self) -> bool {
292        matches!(
293            self,
294            PrimitiveType::Int8
295                | PrimitiveType::Int16
296                | PrimitiveType::Int24
297                | PrimitiveType::Int32
298                | PrimitiveType::Int40
299                | PrimitiveType::Int48
300                | PrimitiveType::Int56
301                | PrimitiveType::Int64
302                | PrimitiveType::Int72
303                | PrimitiveType::Int80
304                | PrimitiveType::Int88
305                | PrimitiveType::Int96
306                | PrimitiveType::Int104
307                | PrimitiveType::Int112
308                | PrimitiveType::Int120
309                | PrimitiveType::Int128
310                | PrimitiveType::Int136
311                | PrimitiveType::Int144
312                | PrimitiveType::Int152
313                | PrimitiveType::Int160
314                | PrimitiveType::Int168
315                | PrimitiveType::Int176
316                | PrimitiveType::Int184
317                | PrimitiveType::Int192
318                | PrimitiveType::Int200
319                | PrimitiveType::Int208
320                | PrimitiveType::Int216
321                | PrimitiveType::Int224
322                | PrimitiveType::Int232
323                | PrimitiveType::Int240
324                | PrimitiveType::Int248
325                | PrimitiveType::Int256
326        )
327    }
328
329    pub fn is_fixed_bytes(&self) -> bool {
330        matches!(
331            self,
332            PrimitiveType::Bytes1
333                | PrimitiveType::Bytes2
334                | PrimitiveType::Bytes3
335                | PrimitiveType::Bytes4
336                | PrimitiveType::Bytes5
337                | PrimitiveType::Bytes6
338                | PrimitiveType::Bytes7
339                | PrimitiveType::Bytes8
340                | PrimitiveType::Bytes9
341                | PrimitiveType::Bytes10
342                | PrimitiveType::Bytes11
343                | PrimitiveType::Bytes12
344                | PrimitiveType::Bytes13
345                | PrimitiveType::Bytes14
346                | PrimitiveType::Bytes15
347                | PrimitiveType::Bytes16
348                | PrimitiveType::Bytes17
349                | PrimitiveType::Bytes18
350                | PrimitiveType::Bytes19
351                | PrimitiveType::Bytes20
352                | PrimitiveType::Bytes21
353                | PrimitiveType::Bytes22
354                | PrimitiveType::Bytes23
355                | PrimitiveType::Bytes24
356                | PrimitiveType::Bytes25
357                | PrimitiveType::Bytes26
358                | PrimitiveType::Bytes27
359                | PrimitiveType::Bytes28
360                | PrimitiveType::Bytes29
361                | PrimitiveType::Bytes30
362                | PrimitiveType::Bytes31
363                | PrimitiveType::Bytes32
364        )
365    }
366
367    pub fn parse(s: &str) -> Option<Self> {
368        match s {
369            // uint aliases
370            "uint" | "uint256" => Some(Self::Uint256),
371            "uint8" => Some(Self::Uint8),
372            "uint16" => Some(Self::Uint16),
373            "uint24" => Some(Self::Uint24),
374            "uint32" => Some(Self::Uint32),
375            "uint40" => Some(Self::Uint40),
376            "uint48" => Some(Self::Uint48),
377            "uint56" => Some(Self::Uint56),
378            "uint64" => Some(Self::Uint64),
379            "uint72" => Some(Self::Uint72),
380            "uint80" => Some(Self::Uint80),
381            "uint88" => Some(Self::Uint88),
382            "uint96" => Some(Self::Uint96),
383            "uint104" => Some(Self::Uint104),
384            "uint112" => Some(Self::Uint112),
385            "uint120" => Some(Self::Uint120),
386            "uint128" => Some(Self::Uint128),
387            "uint136" => Some(Self::Uint136),
388            "uint144" => Some(Self::Uint144),
389            "uint152" => Some(Self::Uint152),
390            "uint160" => Some(Self::Uint160),
391            "uint168" => Some(Self::Uint168),
392            "uint176" => Some(Self::Uint176),
393            "uint184" => Some(Self::Uint184),
394            "uint192" => Some(Self::Uint192),
395            "uint200" => Some(Self::Uint200),
396            "uint208" => Some(Self::Uint208),
397            "uint216" => Some(Self::Uint216),
398            "uint224" => Some(Self::Uint224),
399            "uint232" => Some(Self::Uint232),
400            "uint240" => Some(Self::Uint240),
401            "uint248" => Some(Self::Uint248),
402            // int aliases
403            "int" | "int256" => Some(Self::Int256),
404            "int8" => Some(Self::Int8),
405            "int16" => Some(Self::Int16),
406            "int24" => Some(Self::Int24),
407            "int32" => Some(Self::Int32),
408            "int40" => Some(Self::Int40),
409            "int48" => Some(Self::Int48),
410            "int56" => Some(Self::Int56),
411            "int64" => Some(Self::Int64),
412            "int72" => Some(Self::Int72),
413            "int80" => Some(Self::Int80),
414            "int88" => Some(Self::Int88),
415            "int96" => Some(Self::Int96),
416            "int104" => Some(Self::Int104),
417            "int112" => Some(Self::Int112),
418            "int120" => Some(Self::Int120),
419            "int128" => Some(Self::Int128),
420            "int136" => Some(Self::Int136),
421            "int144" => Some(Self::Int144),
422            "int152" => Some(Self::Int152),
423            "int160" => Some(Self::Int160),
424            "int168" => Some(Self::Int168),
425            "int176" => Some(Self::Int176),
426            "int184" => Some(Self::Int184),
427            "int192" => Some(Self::Int192),
428            "int200" => Some(Self::Int200),
429            "int208" => Some(Self::Int208),
430            "int216" => Some(Self::Int216),
431            "int224" => Some(Self::Int224),
432            "int232" => Some(Self::Int232),
433            "int240" => Some(Self::Int240),
434            "int248" => Some(Self::Int248),
435            // Other types
436            "bool" => Some(Self::Bool),
437            "address" => Some(Self::Address),
438            "signer" => Some(Self::Signer),
439            "string" => Some(Self::String),
440            "bytes" => Some(Self::Bytes),
441            "bytes1" => Some(Self::Bytes1),
442            "bytes2" => Some(Self::Bytes2),
443            "bytes3" => Some(Self::Bytes3),
444            "bytes4" => Some(Self::Bytes4),
445            "bytes5" => Some(Self::Bytes5),
446            "bytes6" => Some(Self::Bytes6),
447            "bytes7" => Some(Self::Bytes7),
448            "bytes8" => Some(Self::Bytes8),
449            "bytes9" => Some(Self::Bytes9),
450            "bytes10" => Some(Self::Bytes10),
451            "bytes11" => Some(Self::Bytes11),
452            "bytes12" => Some(Self::Bytes12),
453            "bytes13" => Some(Self::Bytes13),
454            "bytes14" => Some(Self::Bytes14),
455            "bytes15" => Some(Self::Bytes15),
456            "bytes16" => Some(Self::Bytes16),
457            "bytes17" => Some(Self::Bytes17),
458            "bytes18" => Some(Self::Bytes18),
459            "bytes19" => Some(Self::Bytes19),
460            "bytes20" => Some(Self::Bytes20),
461            "bytes21" => Some(Self::Bytes21),
462            "bytes22" => Some(Self::Bytes22),
463            "bytes23" => Some(Self::Bytes23),
464            "bytes24" => Some(Self::Bytes24),
465            "bytes25" => Some(Self::Bytes25),
466            "bytes26" => Some(Self::Bytes26),
467            "bytes27" => Some(Self::Bytes27),
468            "bytes28" => Some(Self::Bytes28),
469            "bytes29" => Some(Self::Bytes29),
470            "bytes30" => Some(Self::Bytes30),
471            "bytes31" => Some(Self::Bytes31),
472            "bytes32" => Some(Self::Bytes32),
473            _ => None,
474        }
475    }
476}
477
478impl fmt::Display for PrimitiveType {
479    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
480        match self {
481            PrimitiveType::Uint8 => write!(f, "uint8"),
482            PrimitiveType::Uint16 => write!(f, "uint16"),
483            PrimitiveType::Uint24 => write!(f, "uint24"),
484            PrimitiveType::Uint32 => write!(f, "uint32"),
485            PrimitiveType::Uint40 => write!(f, "uint40"),
486            PrimitiveType::Uint48 => write!(f, "uint48"),
487            PrimitiveType::Uint56 => write!(f, "uint56"),
488            PrimitiveType::Uint64 => write!(f, "uint64"),
489            PrimitiveType::Uint72 => write!(f, "uint72"),
490            PrimitiveType::Uint80 => write!(f, "uint80"),
491            PrimitiveType::Uint88 => write!(f, "uint88"),
492            PrimitiveType::Uint96 => write!(f, "uint96"),
493            PrimitiveType::Uint104 => write!(f, "uint104"),
494            PrimitiveType::Uint112 => write!(f, "uint112"),
495            PrimitiveType::Uint120 => write!(f, "uint120"),
496            PrimitiveType::Uint128 => write!(f, "uint128"),
497            PrimitiveType::Uint136 => write!(f, "uint136"),
498            PrimitiveType::Uint144 => write!(f, "uint144"),
499            PrimitiveType::Uint152 => write!(f, "uint152"),
500            PrimitiveType::Uint160 => write!(f, "uint160"),
501            PrimitiveType::Uint168 => write!(f, "uint168"),
502            PrimitiveType::Uint176 => write!(f, "uint176"),
503            PrimitiveType::Uint184 => write!(f, "uint184"),
504            PrimitiveType::Uint192 => write!(f, "uint192"),
505            PrimitiveType::Uint200 => write!(f, "uint200"),
506            PrimitiveType::Uint208 => write!(f, "uint208"),
507            PrimitiveType::Uint216 => write!(f, "uint216"),
508            PrimitiveType::Uint224 => write!(f, "uint224"),
509            PrimitiveType::Uint232 => write!(f, "uint232"),
510            PrimitiveType::Uint240 => write!(f, "uint240"),
511            PrimitiveType::Uint248 => write!(f, "uint248"),
512            PrimitiveType::Uint256 => write!(f, "uint256"),
513            PrimitiveType::Int8 => write!(f, "int8"),
514            PrimitiveType::Int16 => write!(f, "int16"),
515            PrimitiveType::Int24 => write!(f, "int24"),
516            PrimitiveType::Int32 => write!(f, "int32"),
517            PrimitiveType::Int40 => write!(f, "int40"),
518            PrimitiveType::Int48 => write!(f, "int48"),
519            PrimitiveType::Int56 => write!(f, "int56"),
520            PrimitiveType::Int64 => write!(f, "int64"),
521            PrimitiveType::Int72 => write!(f, "int72"),
522            PrimitiveType::Int80 => write!(f, "int80"),
523            PrimitiveType::Int88 => write!(f, "int88"),
524            PrimitiveType::Int96 => write!(f, "int96"),
525            PrimitiveType::Int104 => write!(f, "int104"),
526            PrimitiveType::Int112 => write!(f, "int112"),
527            PrimitiveType::Int120 => write!(f, "int120"),
528            PrimitiveType::Int128 => write!(f, "int128"),
529            PrimitiveType::Int136 => write!(f, "int136"),
530            PrimitiveType::Int144 => write!(f, "int144"),
531            PrimitiveType::Int152 => write!(f, "int152"),
532            PrimitiveType::Int160 => write!(f, "int160"),
533            PrimitiveType::Int168 => write!(f, "int168"),
534            PrimitiveType::Int176 => write!(f, "int176"),
535            PrimitiveType::Int184 => write!(f, "int184"),
536            PrimitiveType::Int192 => write!(f, "int192"),
537            PrimitiveType::Int200 => write!(f, "int200"),
538            PrimitiveType::Int208 => write!(f, "int208"),
539            PrimitiveType::Int216 => write!(f, "int216"),
540            PrimitiveType::Int224 => write!(f, "int224"),
541            PrimitiveType::Int232 => write!(f, "int232"),
542            PrimitiveType::Int240 => write!(f, "int240"),
543            PrimitiveType::Int248 => write!(f, "int248"),
544            PrimitiveType::Int256 => write!(f, "int256"),
545            PrimitiveType::Bool => write!(f, "bool"),
546            PrimitiveType::Address => write!(f, "address"),
547            PrimitiveType::Signer => write!(f, "signer"),
548            PrimitiveType::String => write!(f, "string"),
549            PrimitiveType::Bytes => write!(f, "bytes"),
550            PrimitiveType::Bytes1 => write!(f, "bytes1"),
551            PrimitiveType::Bytes2 => write!(f, "bytes2"),
552            PrimitiveType::Bytes3 => write!(f, "bytes3"),
553            PrimitiveType::Bytes4 => write!(f, "bytes4"),
554            PrimitiveType::Bytes5 => write!(f, "bytes5"),
555            PrimitiveType::Bytes6 => write!(f, "bytes6"),
556            PrimitiveType::Bytes7 => write!(f, "bytes7"),
557            PrimitiveType::Bytes8 => write!(f, "bytes8"),
558            PrimitiveType::Bytes9 => write!(f, "bytes9"),
559            PrimitiveType::Bytes10 => write!(f, "bytes10"),
560            PrimitiveType::Bytes11 => write!(f, "bytes11"),
561            PrimitiveType::Bytes12 => write!(f, "bytes12"),
562            PrimitiveType::Bytes13 => write!(f, "bytes13"),
563            PrimitiveType::Bytes14 => write!(f, "bytes14"),
564            PrimitiveType::Bytes15 => write!(f, "bytes15"),
565            PrimitiveType::Bytes16 => write!(f, "bytes16"),
566            PrimitiveType::Bytes17 => write!(f, "bytes17"),
567            PrimitiveType::Bytes18 => write!(f, "bytes18"),
568            PrimitiveType::Bytes19 => write!(f, "bytes19"),
569            PrimitiveType::Bytes20 => write!(f, "bytes20"),
570            PrimitiveType::Bytes21 => write!(f, "bytes21"),
571            PrimitiveType::Bytes22 => write!(f, "bytes22"),
572            PrimitiveType::Bytes23 => write!(f, "bytes23"),
573            PrimitiveType::Bytes24 => write!(f, "bytes24"),
574            PrimitiveType::Bytes25 => write!(f, "bytes25"),
575            PrimitiveType::Bytes26 => write!(f, "bytes26"),
576            PrimitiveType::Bytes27 => write!(f, "bytes27"),
577            PrimitiveType::Bytes28 => write!(f, "bytes28"),
578            PrimitiveType::Bytes29 => write!(f, "bytes29"),
579            PrimitiveType::Bytes30 => write!(f, "bytes30"),
580            PrimitiveType::Bytes31 => write!(f, "bytes31"),
581            PrimitiveType::Bytes32 => write!(f, "bytes32"),
582        }
583    }
584}
585
586/// A named type (struct, enum, contract, interface)
587#[derive(Debug, Clone, PartialEq)]
588pub struct NamedType {
589    pub name: SmolStr,
590    pub type_args: Vec<Type>,
591}
592
593impl NamedType {
594    pub fn new(name: impl Into<SmolStr>) -> Self {
595        Self {
596            name: name.into(),
597            type_args: Vec::new(),
598        }
599    }
600
601    pub fn with_args(name: impl Into<SmolStr>, type_args: Vec<Type>) -> Self {
602        Self {
603            name: name.into(),
604            type_args,
605        }
606    }
607}
608
609impl fmt::Display for NamedType {
610    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
611        write!(f, "{}", self.name)?;
612        if !self.type_args.is_empty() {
613            write!(f, "<")?;
614            for (i, arg) in self.type_args.iter().enumerate() {
615                if i > 0 {
616                    write!(f, ", ")?;
617                }
618                write!(f, "{}", arg)?;
619            }
620            write!(f, ">")?;
621        }
622        Ok(())
623    }
624}
625
626/// A function type
627#[derive(Debug, Clone, PartialEq)]
628pub struct FunctionType {
629    pub params: Vec<Type>,
630    pub return_type: Box<Type>,
631}
632
633impl fmt::Display for FunctionType {
634    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635        write!(f, "function(")?;
636        for (i, param) in self.params.iter().enumerate() {
637            if i > 0 {
638                write!(f, ", ")?;
639            }
640            write!(f, "{}", param)?;
641        }
642        write!(f, ") returns ({})", self.return_type)
643    }
644}
645
646/// A type variable for inference
647#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
648pub struct TypeVar(pub u32);
649
650impl fmt::Display for TypeVar {
651    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
652        write!(f, "?T{}", self.0)
653    }
654}
655
656/// Type definitions (for structs, enums, etc.)
657#[derive(Debug, Clone)]
658pub enum TypeDef {
659    Struct(StructDef),
660    Enum(EnumDef),
661    Contract(ContractDef),
662    Interface(InterfaceDef),
663    Event(EventDef),
664    Error(ErrorDef),
665}
666
667/// Struct type definition
668#[derive(Debug, Clone)]
669pub struct StructDef {
670    pub name: SmolStr,
671    pub type_params: Vec<SmolStr>,
672    pub fields: IndexMap<SmolStr, Type>,
673}
674
675/// Enum type definition (Solidity-style: simple variants only)
676#[derive(Debug, Clone)]
677pub struct EnumDef {
678    pub name: SmolStr,
679    pub variants: Vec<SmolStr>,
680}
681
682/// Contract type definition
683#[derive(Debug, Clone)]
684pub struct ContractDef {
685    pub name: SmolStr,
686    pub type_params: Vec<SmolStr>,
687    pub bases: Vec<SmolStr>,
688    pub state_fields: IndexMap<SmolStr, Type>,
689    pub methods: IndexMap<SmolStr, FunctionType>,
690    pub modifiers: IndexMap<SmolStr, ModifierType>,
691}
692
693/// Interface type definition
694#[derive(Debug, Clone)]
695pub struct InterfaceDef {
696    pub name: SmolStr,
697    pub bases: Vec<SmolStr>,
698    pub methods: IndexMap<SmolStr, FunctionType>,
699}
700
701/// Event type definition
702#[derive(Debug, Clone)]
703pub struct EventDef {
704    pub name: SmolStr,
705    pub params: Vec<EventParam>,
706}
707
708/// Event parameter
709#[derive(Debug, Clone)]
710pub struct EventParam {
711    pub name: SmolStr,
712    pub ty: Type,
713    pub indexed: bool,
714}
715
716/// Error type definition
717#[derive(Debug, Clone)]
718pub struct ErrorDef {
719    pub name: SmolStr,
720    pub params: Vec<ErrorParam>,
721}
722
723/// Error parameter
724#[derive(Debug, Clone)]
725pub struct ErrorParam {
726    pub name: SmolStr,
727    pub ty: Type,
728}
729
730/// Modifier type definition
731#[derive(Debug, Clone)]
732pub struct ModifierType {
733    pub name: SmolStr,
734    pub params: Vec<Type>,
735}