cl_ast/ast_impl/
weight_of.rs

1//! Approximates the size of an AST
2
3use std::mem::size_of_val;
4
5use crate::ast::*;
6use cl_structures::{intern::interned::Interned, span::Span};
7
8/// Approximates the size of an AST without including indirection (pointers) or padding
9pub trait WeightOf {
10    /// Approximates the size of a syntax tree without including pointer/indirection or padding.
11    fn weight_of(&self) -> usize;
12}
13
14impl WeightOf for File {
15    fn weight_of(&self) -> usize {
16        let Self { name, items } = self;
17        name.weight_of() + items.weight_of()
18    }
19}
20
21impl WeightOf for Attrs {
22    fn weight_of(&self) -> usize {
23        let Self { meta } = self;
24        meta.weight_of()
25    }
26}
27
28impl WeightOf for Meta {
29    fn weight_of(&self) -> usize {
30        let Self { name, kind } = self;
31        name.weight_of() + kind.weight_of()
32    }
33}
34
35impl WeightOf for MetaKind {
36    fn weight_of(&self) -> usize {
37        match self {
38            MetaKind::Plain => size_of_val(self),
39            MetaKind::Equals(v) => v.weight_of(),
40            MetaKind::Func(v) => v.weight_of(),
41        }
42    }
43}
44
45impl WeightOf for Item {
46    fn weight_of(&self) -> usize {
47        let Self { span, attrs, vis, kind } = self;
48        span.weight_of() + attrs.weight_of() + vis.weight_of() + kind.weight_of()
49    }
50}
51
52impl WeightOf for ItemKind {
53    fn weight_of(&self) -> usize {
54        match self {
55            ItemKind::Module(v) => v.weight_of(),
56            ItemKind::Alias(v) => v.weight_of(),
57            ItemKind::Enum(v) => v.weight_of(),
58            ItemKind::Struct(v) => v.weight_of(),
59            ItemKind::Const(v) => v.weight_of(),
60            ItemKind::Static(v) => v.weight_of(),
61            ItemKind::Function(v) => v.weight_of(),
62            ItemKind::Impl(v) => v.weight_of(),
63            ItemKind::Use(v) => v.weight_of(),
64        }
65    }
66}
67
68impl WeightOf for Generics {
69    fn weight_of(&self) -> usize {
70        let Self { vars } = self;
71        vars.iter().map(|v| v.weight_of()).sum()
72    }
73}
74
75impl WeightOf for Module {
76    fn weight_of(&self) -> usize {
77        let Self { name, file } = self;
78        name.weight_of() + file.weight_of()
79    }
80}
81
82impl WeightOf for Alias {
83    fn weight_of(&self) -> usize {
84        let Self { name, from } = self;
85        name.weight_of() + from.weight_of()
86    }
87}
88
89impl WeightOf for Const {
90    fn weight_of(&self) -> usize {
91        let Self { name, ty, init } = self;
92        name.weight_of() + ty.weight_of() + init.weight_of()
93    }
94}
95
96impl WeightOf for Static {
97    fn weight_of(&self) -> usize {
98        let Self { mutable, name, ty, init } = self;
99        mutable.weight_of() + name.weight_of() + ty.weight_of() + init.weight_of()
100    }
101}
102
103impl WeightOf for Function {
104    fn weight_of(&self) -> usize {
105        let Self { name, gens, sign, bind, body } = self;
106        name.weight_of() + gens.weight_of() + sign.weight_of() + bind.weight_of() + body.weight_of()
107    }
108}
109
110impl WeightOf for Struct {
111    fn weight_of(&self) -> usize {
112        let Self { name, gens, kind } = self;
113        name.weight_of() + gens.weight_of() + kind.weight_of()
114    }
115}
116
117impl WeightOf for StructKind {
118    fn weight_of(&self) -> usize {
119        match self {
120            StructKind::Empty => size_of_val(self),
121            StructKind::Tuple(items) => items.weight_of(),
122            StructKind::Struct(sm) => sm.weight_of(),
123        }
124    }
125}
126
127impl WeightOf for StructMember {
128    fn weight_of(&self) -> usize {
129        let Self { vis, name, ty } = self;
130        vis.weight_of() + name.weight_of() + ty.weight_of()
131    }
132}
133
134impl WeightOf for Enum {
135    fn weight_of(&self) -> usize {
136        let Self { name, gens, variants } = self;
137        name.weight_of() + gens.weight_of() + variants.weight_of()
138    }
139}
140
141impl WeightOf for Variant {
142    fn weight_of(&self) -> usize {
143        let Self { name, kind, body } = self;
144        name.weight_of() + kind.weight_of() + body.weight_of()
145    }
146}
147
148impl WeightOf for Impl {
149    fn weight_of(&self) -> usize {
150        let Self { target, body } = self;
151        target.weight_of() + body.weight_of()
152    }
153}
154
155impl WeightOf for ImplKind {
156    fn weight_of(&self) -> usize {
157        match self {
158            ImplKind::Type(ty) => ty.weight_of(),
159            ImplKind::Trait { impl_trait, for_type } => {
160                impl_trait.weight_of() + for_type.weight_of()
161            }
162        }
163    }
164}
165
166impl WeightOf for Use {
167    fn weight_of(&self) -> usize {
168        let Self { absolute, tree } = self;
169        absolute.weight_of() + tree.weight_of()
170    }
171}
172
173impl WeightOf for UseTree {
174    fn weight_of(&self) -> usize {
175        match self {
176            UseTree::Tree(tr) => tr.weight_of(),
177            UseTree::Path(pa, tr) => pa.weight_of() + tr.weight_of(),
178            UseTree::Alias(src, dst) => src.weight_of() + dst.weight_of(),
179            UseTree::Name(src) => src.weight_of(),
180            UseTree::Glob => size_of_val(self),
181        }
182    }
183}
184
185impl WeightOf for Ty {
186    fn weight_of(&self) -> usize {
187        let Self { span, kind } = self;
188        span.weight_of() + kind.weight_of()
189    }
190}
191
192impl WeightOf for TyKind {
193    fn weight_of(&self) -> usize {
194        match self {
195            TyKind::Never | TyKind::Empty | TyKind::Infer => size_of_val(self),
196            TyKind::Path(v) => v.weight_of(),
197            TyKind::Array(v) => v.weight_of(),
198            TyKind::Slice(v) => v.weight_of(),
199            TyKind::Tuple(v) => v.weight_of(),
200            TyKind::Ref(v) => v.weight_of(),
201            TyKind::Fn(v) => v.weight_of(),
202        }
203    }
204}
205
206impl WeightOf for TyArray {
207    fn weight_of(&self) -> usize {
208        let Self { ty, count } = self;
209        ty.weight_of() + count.weight_of()
210    }
211}
212
213impl WeightOf for TySlice {
214    fn weight_of(&self) -> usize {
215        let Self { ty } = self;
216        ty.weight_of()
217    }
218}
219
220impl WeightOf for TyTuple {
221    fn weight_of(&self) -> usize {
222        let Self { types } = self;
223        types.weight_of()
224    }
225}
226
227impl WeightOf for TyRef {
228    fn weight_of(&self) -> usize {
229        let Self { mutable, count, to } = self;
230        mutable.weight_of() + count.weight_of() + to.weight_of()
231    }
232}
233
234impl WeightOf for TyFn {
235    fn weight_of(&self) -> usize {
236        let Self { args, rety } = self;
237        args.weight_of() + rety.weight_of()
238    }
239}
240
241impl WeightOf for Path {
242    fn weight_of(&self) -> usize {
243        let Self { absolute, parts } = self;
244        absolute.weight_of() + parts.weight_of()
245    }
246}
247
248impl WeightOf for PathPart {
249    fn weight_of(&self) -> usize {
250        match self {
251            PathPart::SuperKw => size_of_val(self),
252            PathPart::SelfTy => size_of_val(self),
253            PathPart::Ident(interned) => interned.weight_of(),
254        }
255    }
256}
257
258impl WeightOf for Stmt {
259    fn weight_of(&self) -> usize {
260        let Self { span, kind, semi } = self;
261        span.weight_of() + kind.weight_of() + semi.weight_of()
262    }
263}
264
265impl WeightOf for StmtKind {
266    fn weight_of(&self) -> usize {
267        match self {
268            StmtKind::Empty => size_of_val(self),
269            StmtKind::Item(item) => item.weight_of(),
270            StmtKind::Expr(expr) => expr.weight_of(),
271        }
272    }
273}
274
275impl WeightOf for Expr {
276    fn weight_of(&self) -> usize {
277        let Self { span, kind } = self;
278        span.weight_of() + kind.weight_of()
279    }
280}
281
282impl WeightOf for ExprKind {
283    fn weight_of(&self) -> usize {
284        match self {
285            ExprKind::Empty => size_of_val(self),
286            ExprKind::Closure(v) => v.weight_of(),
287            ExprKind::Quote(v) => v.weight_of(),
288            ExprKind::Let(v) => v.weight_of(),
289            ExprKind::Match(v) => v.weight_of(),
290            ExprKind::Assign(v) => v.weight_of(),
291            ExprKind::Modify(v) => v.weight_of(),
292            ExprKind::Binary(v) => v.weight_of(),
293            ExprKind::Unary(v) => v.weight_of(),
294            ExprKind::Cast(v) => v.weight_of(),
295            ExprKind::Member(v) => v.weight_of(),
296            ExprKind::Index(v) => v.weight_of(),
297            ExprKind::Structor(v) => v.weight_of(),
298            ExprKind::Path(v) => v.weight_of(),
299            ExprKind::Literal(v) => v.weight_of(),
300            ExprKind::Array(v) => v.weight_of(),
301            ExprKind::ArrayRep(v) => v.weight_of(),
302            ExprKind::AddrOf(v) => v.weight_of(),
303            ExprKind::Block(v) => v.weight_of(),
304            ExprKind::Group(v) => v.weight_of(),
305            ExprKind::Tuple(v) => v.weight_of(),
306            ExprKind::While(v) => v.weight_of(),
307            ExprKind::If(v) => v.weight_of(),
308            ExprKind::For(v) => v.weight_of(),
309            ExprKind::Break(v) => v.weight_of(),
310            ExprKind::Return(v) => v.weight_of(),
311            ExprKind::Continue => size_of_val(self),
312        }
313    }
314}
315
316impl WeightOf for Closure {
317    fn weight_of(&self) -> usize {
318        let Self { arg, body } = self;
319        arg.weight_of() + body.weight_of()
320    }
321}
322
323impl WeightOf for Quote {
324    fn weight_of(&self) -> usize {
325        let Self { quote } = self;
326        quote.weight_of()
327    }
328}
329
330impl WeightOf for Let {
331    fn weight_of(&self) -> usize {
332        let Self { mutable, name, ty, init } = self;
333        mutable.weight_of() + name.weight_of() + ty.weight_of() + init.weight_of()
334    }
335}
336
337impl WeightOf for Pattern {
338    fn weight_of(&self) -> usize {
339        match self {
340            Pattern::Name(s) => size_of_val(s),
341            Pattern::Path(p) => p.weight_of(),
342            Pattern::Literal(literal) => literal.weight_of(),
343            Pattern::Rest(Some(pattern)) => pattern.weight_of(),
344            Pattern::Rest(None) => 0,
345            Pattern::Ref(mutability, pattern) => mutability.weight_of() + pattern.weight_of(),
346            Pattern::RangeExc(head, tail) => head.weight_of() + tail.weight_of(),
347            Pattern::RangeInc(head, tail) => head.weight_of() + tail.weight_of(),
348            Pattern::Tuple(patterns) | Pattern::Array(patterns) => patterns.weight_of(),
349            Pattern::Struct(path, items) => {
350                let sitems: usize = items
351                    .iter()
352                    .map(|(name, opt)| name.weight_of() + opt.weight_of())
353                    .sum();
354                path.weight_of() + sitems
355            }
356            Pattern::TupleStruct(path, patterns) => path.weight_of() + patterns.weight_of(),
357        }
358    }
359}
360
361impl WeightOf for Match {
362    fn weight_of(&self) -> usize {
363        let Self { scrutinee, arms } = self;
364        scrutinee.weight_of() + arms.weight_of()
365    }
366}
367
368impl WeightOf for MatchArm {
369    fn weight_of(&self) -> usize {
370        let Self(pattern, expr) = self;
371        pattern.weight_of() + expr.weight_of()
372    }
373}
374
375impl WeightOf for Assign {
376    fn weight_of(&self) -> usize {
377        let Self { parts } = self;
378
379        parts.0.weight_of() + parts.1.weight_of()
380    }
381}
382
383impl WeightOf for Modify {
384    #[rustfmt::skip]
385    fn weight_of(&self) -> usize {
386        let Self { kind, parts } = self;
387        kind.weight_of()
388            + parts.0.weight_of()
389            + parts.1.weight_of()
390    }
391}
392
393impl WeightOf for Binary {
394    fn weight_of(&self) -> usize {
395        let Self { kind, parts } = self;
396
397        kind.weight_of() + parts.0.weight_of() + parts.1.weight_of()
398    }
399}
400
401impl WeightOf for Unary {
402    #[rustfmt::skip]
403    fn weight_of(&self) -> usize {
404        let Self { kind, tail } = self;
405         kind.weight_of() + tail.weight_of()
406    }
407}
408
409impl WeightOf for Cast {
410    fn weight_of(&self) -> usize {
411        let Self { head, ty } = self;
412        head.weight_of() + ty.weight_of()
413    }
414}
415
416impl WeightOf for Member {
417    fn weight_of(&self) -> usize {
418        let Self { head, kind } = self;
419
420        head.weight_of() + kind.weight_of() // accounting
421    }
422}
423
424impl WeightOf for MemberKind {
425    fn weight_of(&self) -> usize {
426        match self {
427            MemberKind::Call(_, tuple) => tuple.weight_of(),
428            MemberKind::Struct(_) => 0,
429            MemberKind::Tuple(literal) => literal.weight_of(),
430        }
431    }
432}
433
434impl WeightOf for Index {
435    fn weight_of(&self) -> usize {
436        let Self { head, indices } = self;
437        head.weight_of() + indices.weight_of()
438    }
439}
440
441impl WeightOf for Literal {
442    fn weight_of(&self) -> usize {
443        match self {
444            Literal::Bool(v) => v.weight_of(),
445            Literal::Char(v) => v.weight_of(),
446            Literal::Int(v) => v.weight_of(),
447            Literal::Float(v) => v.weight_of(),
448            Literal::String(v) => v.weight_of(),
449        }
450    }
451}
452
453impl WeightOf for Structor {
454    fn weight_of(&self) -> usize {
455        let Self { to, init } = self;
456        to.weight_of() + init.weight_of()
457    }
458}
459
460impl WeightOf for Fielder {
461    fn weight_of(&self) -> usize {
462        let Self { name, init } = self;
463        name.weight_of() + init.weight_of()
464    }
465}
466
467impl WeightOf for Array {
468    fn weight_of(&self) -> usize {
469        let Self { values } = self;
470        values.weight_of()
471    }
472}
473
474impl WeightOf for ArrayRep {
475    fn weight_of(&self) -> usize {
476        let Self { value, repeat } = self;
477        value.weight_of() + repeat.weight_of()
478    }
479}
480
481impl WeightOf for AddrOf {
482    fn weight_of(&self) -> usize {
483        let Self { mutable, expr } = self;
484        mutable.weight_of() + expr.weight_of()
485    }
486}
487
488impl WeightOf for Block {
489    fn weight_of(&self) -> usize {
490        let Self { stmts } = self;
491        stmts.weight_of()
492    }
493}
494
495impl WeightOf for Group {
496    fn weight_of(&self) -> usize {
497        let Self { expr } = self;
498        expr.weight_of()
499    }
500}
501
502impl WeightOf for Tuple {
503    fn weight_of(&self) -> usize {
504        let Self { exprs } = self;
505        exprs.weight_of()
506    }
507}
508
509impl WeightOf for While {
510    fn weight_of(&self) -> usize {
511        let Self { cond, pass, fail } = self;
512        cond.weight_of() + pass.weight_of() + fail.weight_of()
513    }
514}
515
516impl WeightOf for If {
517    fn weight_of(&self) -> usize {
518        let Self { cond, pass, fail } = self;
519        cond.weight_of() + pass.weight_of() + fail.weight_of()
520    }
521}
522
523impl WeightOf for For {
524    fn weight_of(&self) -> usize {
525        let Self { bind, cond, pass, fail } = self;
526        bind.weight_of() + cond.weight_of() + pass.weight_of() + fail.weight_of()
527    }
528}
529
530impl WeightOf for Else {
531    fn weight_of(&self) -> usize {
532        let Self { body } = self;
533        body.weight_of()
534    }
535}
536
537impl WeightOf for Break {
538    fn weight_of(&self) -> usize {
539        let Self { body } = self;
540        body.weight_of()
541    }
542}
543
544impl WeightOf for Return {
545    fn weight_of(&self) -> usize {
546        let Self { body } = self;
547        body.weight_of()
548    }
549}
550
551// ------------ SizeOf Blanket Implementations
552
553impl<T: WeightOf> WeightOf for Option<T> {
554    fn weight_of(&self) -> usize {
555        match self {
556            Some(t) => t.weight_of().max(size_of_val(t)),
557            None => size_of_val(self),
558        }
559    }
560}
561
562impl<T: WeightOf> WeightOf for [T] {
563    fn weight_of(&self) -> usize {
564        self.iter().map(WeightOf::weight_of).sum()
565    }
566}
567
568impl<T: WeightOf> WeightOf for Vec<T> {
569    fn weight_of(&self) -> usize {
570        size_of::<Self>() + self.iter().map(WeightOf::weight_of).sum::<usize>()
571    }
572}
573
574impl<T: WeightOf> WeightOf for Box<T> {
575    fn weight_of(&self) -> usize {
576        (**self).weight_of() + size_of::<Self>()
577    }
578}
579
580impl WeightOf for str {
581    fn weight_of(&self) -> usize {
582        self.len()
583    }
584}
585
586impl_size_of! {
587    // primitives
588    u8, u16, u32, u64, u128, usize,
589    i8, i16, i32, i64, i128, isize,
590    f32, f64, bool, char,
591    // cl-structures
592    Span,
593    // cl-ast
594    Visibility, Mutability, Semi, ModifyKind, BinaryKind, UnaryKind
595}
596
597impl<T> WeightOf for Interned<'_, T> {
598    fn weight_of(&self) -> usize {
599        size_of_val(self) // interned values are opaque to SizeOF
600    }
601}
602
603macro impl_size_of($($T:ty),*$(,)?) {
604    $(impl WeightOf for $T {
605        fn weight_of(&self) -> usize {
606            ::std::mem::size_of_val(self)
607        }
608    })*
609}