sway_core/language/parsed/expression/
scrutinee.rs1use crate::{
2 engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext},
3 language::{CallPath, Literal},
4 TypeInfo,
5};
6
7use sway_error::handler::ErrorEmitted;
8use sway_types::{ident::Ident, span::Span, Spanned};
9
10#[allow(clippy::enum_variant_names)]
14#[derive(Debug, Clone)]
15pub enum Scrutinee {
16 Or {
17 elems: Vec<Scrutinee>,
18 span: Span,
19 },
20 CatchAll {
21 span: Span,
22 },
23 Literal {
24 value: Literal,
25 span: Span,
26 },
27 Variable {
28 name: Ident,
29 span: Span,
30 },
31 AmbiguousSingleIdent(Ident),
32 StructScrutinee {
33 struct_name: CallPath,
34 fields: Vec<StructScrutineeField>,
35 span: Span,
36 },
37 EnumScrutinee {
38 call_path: CallPath,
39 value: Box<Scrutinee>,
40 span: Span,
41 },
42 Tuple {
43 elems: Vec<Scrutinee>,
44 span: Span,
45 },
46 Error {
48 spans: Box<[Span]>,
49 err: ErrorEmitted,
50 },
51}
52
53impl EqWithEngines for Scrutinee {}
54impl PartialEqWithEngines for Scrutinee {
55 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
56 match (self, other) {
57 (
58 Scrutinee::Or { elems, span },
59 Scrutinee::Or {
60 elems: r_elems,
61 span: r_span,
62 },
63 ) => elems.eq(r_elems, ctx) && span.eq(r_span),
64 (
65 Scrutinee::Literal { value, span },
66 Scrutinee::Literal {
67 value: r_value,
68 span: r_span,
69 },
70 ) => value.eq(r_value) && span.eq(r_span),
71 (
72 Scrutinee::Variable { name, span },
73 Scrutinee::Variable {
74 name: r_name,
75 span: r_span,
76 },
77 ) => name.eq(r_name) && span.eq(r_span),
78 (Scrutinee::AmbiguousSingleIdent(ident), Scrutinee::AmbiguousSingleIdent(r_ident)) => {
79 ident.eq(r_ident)
80 }
81 (
82 Scrutinee::StructScrutinee {
83 struct_name,
84 fields,
85 span,
86 },
87 Scrutinee::StructScrutinee {
88 struct_name: r_struct_name,
89 fields: r_fields,
90 span: r_span,
91 },
92 ) => {
93 PartialEqWithEngines::eq(struct_name, r_struct_name, ctx)
94 && fields.eq(r_fields, ctx)
95 && span.eq(r_span)
96 }
97 (
98 Scrutinee::EnumScrutinee {
99 call_path,
100 value,
101 span,
102 },
103 Scrutinee::EnumScrutinee {
104 call_path: r_call_path,
105 value: r_value,
106 span: r_span,
107 },
108 ) => {
109 PartialEqWithEngines::eq(call_path, r_call_path, ctx)
110 && value.eq(r_value, ctx)
111 && span.eq(r_span)
112 }
113 (
114 Scrutinee::Tuple { elems, span },
115 Scrutinee::Tuple {
116 elems: r_elems,
117 span: r_span,
118 },
119 ) => elems.eq(r_elems, ctx) && span.eq(r_span),
120 (
121 Scrutinee::Error { spans, err },
122 Scrutinee::Error {
123 spans: r_spans,
124 err: r_err,
125 },
126 ) => spans.eq(r_spans) && err.eq(r_err),
127 _ => false,
128 }
129 }
130}
131
132#[derive(Debug, Clone)]
133#[allow(clippy::large_enum_variant)]
134pub enum StructScrutineeField {
135 Rest {
136 span: Span,
137 },
138 Field {
139 field: Ident,
140 scrutinee: Option<Scrutinee>,
141 span: Span,
142 },
143}
144
145impl EqWithEngines for StructScrutineeField {}
146impl PartialEqWithEngines for StructScrutineeField {
147 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
148 match (self, other) {
149 (StructScrutineeField::Rest { span }, StructScrutineeField::Rest { span: r_span }) => {
150 span == r_span
151 }
152 (
153 StructScrutineeField::Field {
154 field,
155 scrutinee,
156 span,
157 },
158 StructScrutineeField::Field {
159 field: r_field,
160 scrutinee: r_scrutinee,
161 span: r_span,
162 },
163 ) => field.eq(r_field) && scrutinee.eq(r_scrutinee, ctx) && span.eq(r_span),
164 _ => false,
165 }
166 }
167}
168
169impl Spanned for Scrutinee {
170 fn span(&self) -> Span {
171 match self {
172 Scrutinee::Or { span, .. } => span.clone(),
173 Scrutinee::CatchAll { span } => span.clone(),
174 Scrutinee::Literal { span, .. } => span.clone(),
175 Scrutinee::Variable { span, .. } => span.clone(),
176 Scrutinee::AmbiguousSingleIdent(ident) => ident.span(),
177 Scrutinee::StructScrutinee { span, .. } => span.clone(),
178 Scrutinee::EnumScrutinee { span, .. } => span.clone(),
179 Scrutinee::Tuple { span, .. } => span.clone(),
180 Scrutinee::Error { spans, .. } => spans
181 .iter()
182 .cloned()
183 .reduce(|s1: Span, s2: Span| Span::join(s1, &s2))
184 .unwrap(),
185 }
186 }
187}
188
189impl Scrutinee {
190 pub(crate) fn gather_approximate_typeinfo_dependencies(&self) -> Vec<TypeInfo> {
244 match self {
245 Scrutinee::StructScrutinee {
246 struct_name,
247 fields,
248 ..
249 } => {
250 let name = vec![TypeInfo::Custom {
251 qualified_call_path: struct_name.clone().into(),
252 type_arguments: None,
253 }];
254 let fields = fields
255 .iter()
256 .flat_map(|f| match f {
257 StructScrutineeField::Field {
258 scrutinee: Some(scrutinee),
259 ..
260 } => scrutinee.gather_approximate_typeinfo_dependencies(),
261 _ => vec![],
262 })
263 .collect::<Vec<TypeInfo>>();
264 [name, fields].concat()
265 }
266 Scrutinee::EnumScrutinee {
267 call_path, value, ..
268 } => {
269 let enum_name = call_path.prefixes.last().unwrap_or(&call_path.suffix);
270 let name = vec![TypeInfo::Custom {
271 qualified_call_path: enum_name.clone().into(),
272 type_arguments: None,
273 }];
274 let value = value.gather_approximate_typeinfo_dependencies();
275 [name, value].concat()
276 }
277 Scrutinee::Tuple { elems, .. } | Scrutinee::Or { elems, .. } => elems
278 .iter()
279 .flat_map(|scrutinee| scrutinee.gather_approximate_typeinfo_dependencies())
280 .collect::<Vec<TypeInfo>>(),
281 Scrutinee::Literal { .. }
282 | Scrutinee::CatchAll { .. }
283 | Scrutinee::AmbiguousSingleIdent(..)
284 | Scrutinee::Variable { .. }
285 | Scrutinee::Error { .. } => {
286 vec![]
287 }
288 }
289 }
290}