midenc_hir/pass/
specialization.rs1use crate::{
2 traits::BranchOpInterface, Context, EntityMut, EntityRef, Op, Operation, OperationName,
3 OperationRef, Symbol, SymbolTable,
4};
5
6pub trait PassTarget {
7 fn target_name(context: &Context) -> Option<OperationName>;
8 fn into_target(op: &OperationRef) -> EntityRef<'_, Self>;
9 fn into_target_mut(op: &mut OperationRef) -> EntityMut<'_, Self>;
10}
11
12impl<T: 'static> PassTarget for T {
13 default fn target_name(_context: &Context) -> Option<OperationName> {
14 None
15 }
16
17 #[inline]
18 #[track_caller]
19 default fn into_target(op: &OperationRef) -> EntityRef<'_, T> {
20 EntityRef::map(op.borrow(), |t| {
21 t.downcast_ref::<T>().unwrap_or_else(|| expected_type::<T>(op))
22 })
23 }
24
25 #[inline]
26 #[track_caller]
27 default fn into_target_mut(op: &mut OperationRef) -> EntityMut<'_, T> {
28 EntityMut::map(op.borrow_mut(), |t| {
29 t.downcast_mut::<T>().unwrap_or_else(|| expected_type::<T>(op))
30 })
31 }
32}
33impl PassTarget for Operation {
34 #[inline(always)]
35 fn target_name(_context: &Context) -> Option<OperationName> {
36 None
37 }
38
39 #[inline]
40 #[track_caller]
41 fn into_target(op: &OperationRef) -> EntityRef<'_, Operation> {
42 op.borrow()
43 }
44
45 #[inline]
46 #[track_caller]
47 fn into_target_mut(op: &mut OperationRef) -> EntityMut<'_, Operation> {
48 op.borrow_mut()
49 }
50}
51impl PassTarget for dyn Op {
52 #[inline(always)]
53 fn target_name(_context: &Context) -> Option<OperationName> {
54 None
55 }
56
57 fn into_target(op: &OperationRef) -> EntityRef<'_, dyn Op> {
58 EntityRef::map(op.borrow(), |op| op.as_trait::<dyn Op>().unwrap())
59 }
60
61 fn into_target_mut(op: &mut OperationRef) -> EntityMut<'_, dyn Op> {
62 EntityMut::map(op.borrow_mut(), |op| op.as_trait_mut::<dyn Op>().unwrap())
63 }
64}
65impl PassTarget for dyn BranchOpInterface {
66 #[inline(always)]
67 fn target_name(_context: &Context) -> Option<OperationName> {
68 None
69 }
70
71 #[track_caller]
72 fn into_target(op: &OperationRef) -> EntityRef<'_, dyn BranchOpInterface> {
73 EntityRef::map(op.borrow(), |t| {
74 t.as_trait::<dyn BranchOpInterface>()
75 .unwrap_or_else(|| expected_implementation::<dyn BranchOpInterface>(op))
76 })
77 }
78
79 #[track_caller]
80 fn into_target_mut(op: &mut OperationRef) -> EntityMut<'_, dyn BranchOpInterface> {
81 EntityMut::map(op.borrow_mut(), |t| {
82 t.as_trait_mut::<dyn BranchOpInterface>()
83 .unwrap_or_else(|| expected_implementation::<dyn BranchOpInterface>(op))
84 })
85 }
86}
87impl PassTarget for dyn Symbol {
88 #[inline(always)]
89 fn target_name(_context: &Context) -> Option<OperationName> {
90 None
91 }
92
93 #[track_caller]
94 fn into_target(op: &OperationRef) -> EntityRef<'_, dyn Symbol> {
95 EntityRef::map(op.borrow(), |t| {
96 t.as_trait::<dyn Symbol>()
97 .unwrap_or_else(|| expected_implementation::<dyn Symbol>(op))
98 })
99 }
100
101 #[track_caller]
102 fn into_target_mut(op: &mut OperationRef) -> EntityMut<'_, dyn Symbol> {
103 EntityMut::map(op.borrow_mut(), |t| {
104 t.as_trait_mut::<dyn Symbol>()
105 .unwrap_or_else(|| expected_implementation::<dyn Symbol>(op))
106 })
107 }
108}
109impl PassTarget for dyn SymbolTable + 'static {
110 #[inline(always)]
111 fn target_name(_context: &Context) -> Option<OperationName> {
112 None
113 }
114
115 #[track_caller]
116 fn into_target(op: &OperationRef) -> EntityRef<'_, dyn SymbolTable + 'static> {
117 EntityRef::map(op.borrow(), |t| {
118 t.as_trait::<dyn SymbolTable>()
119 .unwrap_or_else(|| expected_implementation::<dyn SymbolTable>(op))
120 })
121 }
122
123 #[track_caller]
124 fn into_target_mut(op: &mut OperationRef) -> EntityMut<'_, dyn SymbolTable + 'static> {
125 EntityMut::map(op.borrow_mut(), |t| {
126 t.as_trait_mut::<dyn SymbolTable>()
127 .unwrap_or_else(|| expected_implementation::<dyn SymbolTable>(op))
128 })
129 }
130}
131
132#[cold]
133#[inline(never)]
134#[track_caller]
135fn expected_type<T: 'static>(op: &OperationRef) -> ! {
136 panic!(
137 "expected operation '{}' to be a `{}`",
138 op.borrow().name(),
139 core::any::type_name::<T>(),
140 )
141}
142
143#[cold]
144#[inline(never)]
145#[track_caller]
146fn expected_implementation<Trait: ?Sized + 'static>(op: &OperationRef) -> ! {
147 panic!(
148 "expected '{}' to implement `{}`, but no vtable was found",
149 op.borrow().name(),
150 core::any::type_name::<Trait>()
151 )
152}