1use crate::{
2 decl_engine::*,
3 engine_threading::*,
4 has_changes,
5 language::{ty::*, *},
6 semantic_analysis::{
7 TyNodeDepGraphEdge, TyNodeDepGraphEdgeInfo, TypeCheckAnalysis, TypeCheckAnalysisContext,
8 TypeCheckContext, TypeCheckFinalization, TypeCheckFinalizationContext,
9 },
10 type_system::*,
11};
12use indexmap::IndexMap;
13use serde::{Deserialize, Serialize};
14use std::{
15 collections::VecDeque,
16 fmt::{self, Write},
17 hash::{Hash, Hasher},
18};
19use sway_error::handler::{ErrorEmitted, Handler};
20use sway_types::{Ident, Named, Span, Spanned};
21
22#[derive(Clone, Debug, Serialize, Deserialize)]
23pub enum TyExpressionVariant {
24 Literal(Literal),
25 FunctionApplication {
26 call_path: CallPath,
27 arguments: Vec<(Ident, TyExpression)>,
28 fn_ref: DeclRefFunction,
29 selector: Option<ContractCallParams>,
30 type_binding: Option<TypeBinding<()>>,
32 call_path_typeid: Option<TypeId>,
34 contract_call_params: IndexMap<String, TyExpression>,
35 contract_caller: Option<Box<TyExpression>>,
36 },
37 LazyOperator {
38 op: LazyOp,
39 lhs: Box<TyExpression>,
40 rhs: Box<TyExpression>,
41 },
42 ConstantExpression {
43 span: Span,
44 decl: Box<TyConstantDecl>,
45 call_path: Option<CallPath>,
46 },
47 ConfigurableExpression {
48 span: Span,
49 decl: Box<TyConfigurableDecl>,
50 call_path: Option<CallPath>,
51 },
52 ConstGenericExpression {
53 span: Span,
54 decl: Box<TyConstGenericDecl>,
55 call_path: Option<CallPath>,
56 },
57 VariableExpression {
58 name: Ident,
59 span: Span,
60 mutability: VariableMutability,
61 call_path: Option<CallPath>,
62 },
63 Tuple {
64 fields: Vec<TyExpression>,
65 },
66 ArrayExplicit {
67 elem_type: TypeId,
68 contents: Vec<TyExpression>,
69 },
70 ArrayRepeat {
71 elem_type: TypeId,
72 value: Box<TyExpression>,
73 length: Box<TyExpression>,
74 },
75 ArrayIndex {
76 prefix: Box<TyExpression>,
77 index: Box<TyExpression>,
78 },
79 StructExpression {
80 struct_id: DeclId<TyStructDecl>,
81 fields: Vec<TyStructExpressionField>,
82 instantiation_span: Span,
83 call_path_binding: TypeBinding<CallPath>,
84 },
85 CodeBlock(TyCodeBlock),
86 FunctionParameter,
88 MatchExp {
89 desugared: Box<TyExpression>,
90 scrutinees: Vec<TyScrutinee>,
91 },
92 IfExp {
93 condition: Box<TyExpression>,
94 then: Box<TyExpression>,
95 r#else: Option<Box<TyExpression>>,
96 },
97 AsmExpression {
98 registers: Vec<TyAsmRegisterDeclaration>,
99 body: Vec<AsmOp>,
100 returns: Option<(AsmRegister, Span)>,
101 whole_block_span: Span,
102 },
103 StructFieldAccess {
106 prefix: Box<TyExpression>,
107 field_to_access: TyStructField,
108 field_instantiation_span: Span,
109 resolved_type_of_parent: TypeId,
117 },
118 TupleElemAccess {
119 prefix: Box<TyExpression>,
120 elem_to_access_num: usize,
121 resolved_type_of_parent: TypeId,
129 elem_to_access_span: Span,
130 },
131 EnumInstantiation {
132 enum_ref: DeclRef<DeclId<TyEnumDecl>>,
133 variant_name: Ident,
135 tag: usize,
136 contents: Option<Box<TyExpression>>,
137 variant_instantiation_span: Span,
141 call_path_binding: TypeBinding<CallPath>,
142 call_path_decl: ty::TyDecl,
144 },
145 AbiCast {
146 abi_name: CallPath,
147 address: Box<TyExpression>,
148 #[allow(dead_code)]
149 span: Span,
151 },
152 StorageAccess(TyStorageAccess),
153 IntrinsicFunction(TyIntrinsicFunctionKind),
154 AbiName(AbiName),
156 EnumTag {
158 exp: Box<TyExpression>,
159 },
160 UnsafeDowncast {
162 exp: Box<TyExpression>,
163 variant: TyEnumVariant,
164 call_path_decl: ty::TyDecl,
166 },
167 WhileLoop {
168 condition: Box<TyExpression>,
169 body: TyCodeBlock,
170 },
171 ForLoop {
172 desugared: Box<TyExpression>,
173 },
174 Break,
175 Continue,
176 Reassignment(Box<TyReassignment>),
177 ImplicitReturn(Box<TyExpression>),
178 Return(Box<TyExpression>),
179 Ref(Box<TyExpression>),
180 Deref(Box<TyExpression>),
181}
182
183impl TyExpressionVariant {
184 pub fn as_literal(&self) -> Option<&Literal> {
185 match self {
186 TyExpressionVariant::Literal(v) => Some(v),
187 _ => None,
188 }
189 }
190}
191
192impl EqWithEngines for TyExpressionVariant {}
193impl PartialEqWithEngines for TyExpressionVariant {
194 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
195 let type_engine = ctx.engines().te();
196 match (self, other) {
197 (Self::Literal(l0), Self::Literal(r0)) => l0 == r0,
198 (
199 Self::FunctionApplication {
200 call_path: l_name,
201 arguments: l_arguments,
202 fn_ref: l_fn_ref,
203 ..
204 },
205 Self::FunctionApplication {
206 call_path: r_name,
207 arguments: r_arguments,
208 fn_ref: r_fn_ref,
209 ..
210 },
211 ) => {
212 l_name == r_name
213 && l_arguments.len() == r_arguments.len()
214 && l_arguments
215 .iter()
216 .zip(r_arguments.iter())
217 .all(|((xa, xb), (ya, yb))| xa == ya && xb.eq(yb, ctx))
218 && l_fn_ref.eq(r_fn_ref, ctx)
219 }
220 (
221 Self::LazyOperator {
222 op: l_op,
223 lhs: l_lhs,
224 rhs: l_rhs,
225 },
226 Self::LazyOperator {
227 op: r_op,
228 lhs: r_lhs,
229 rhs: r_rhs,
230 },
231 ) => l_op == r_op && (**l_lhs).eq(&(**r_lhs), ctx) && (**l_rhs).eq(&(**r_rhs), ctx),
232 (
233 Self::ConstantExpression {
234 call_path: l_call_path,
235 span: l_span,
236 decl: _,
237 },
238 Self::ConstantExpression {
239 call_path: r_call_path,
240 span: r_span,
241 decl: _,
242 },
243 ) => l_call_path == r_call_path && l_span == r_span,
244 (
245 Self::VariableExpression {
246 name: l_name,
247 span: l_span,
248 mutability: l_mutability,
249 call_path: _,
250 },
251 Self::VariableExpression {
252 name: r_name,
253 span: r_span,
254 mutability: r_mutability,
255 call_path: _,
256 },
257 ) => l_name == r_name && l_span == r_span && l_mutability == r_mutability,
258 (Self::Tuple { fields: l_fields }, Self::Tuple { fields: r_fields }) => {
259 l_fields.eq(r_fields, ctx)
260 }
261 (
262 Self::ArrayExplicit {
263 contents: l_contents,
264 ..
265 },
266 Self::ArrayExplicit {
267 contents: r_contents,
268 ..
269 },
270 ) => l_contents.eq(r_contents, ctx),
271 (
272 Self::ArrayIndex {
273 prefix: l_prefix,
274 index: l_index,
275 },
276 Self::ArrayIndex {
277 prefix: r_prefix,
278 index: r_index,
279 },
280 ) => (**l_prefix).eq(&**r_prefix, ctx) && (**l_index).eq(&**r_index, ctx),
281 (
282 Self::StructExpression {
283 struct_id: l_struct_id,
284 fields: l_fields,
285 instantiation_span: l_span,
286 call_path_binding: _,
287 },
288 Self::StructExpression {
289 struct_id: r_struct_id,
290 fields: r_fields,
291 instantiation_span: r_span,
292 call_path_binding: _,
293 },
294 ) => {
295 PartialEqWithEngines::eq(&l_struct_id, &r_struct_id, ctx)
296 && l_fields.eq(r_fields, ctx)
297 && l_span == r_span
298 }
299 (Self::CodeBlock(l0), Self::CodeBlock(r0)) => l0.eq(r0, ctx),
300 (
301 Self::IfExp {
302 condition: l_condition,
303 then: l_then,
304 r#else: l_r,
305 },
306 Self::IfExp {
307 condition: r_condition,
308 then: r_then,
309 r#else: r_r,
310 },
311 ) => {
312 (**l_condition).eq(&**r_condition, ctx)
313 && (**l_then).eq(&**r_then, ctx)
314 && if let (Some(l), Some(r)) = (l_r, r_r) {
315 (**l).eq(&**r, ctx)
316 } else {
317 true
318 }
319 }
320 (
321 Self::AsmExpression {
322 registers: l_registers,
323 body: l_body,
324 returns: l_returns,
325 ..
326 },
327 Self::AsmExpression {
328 registers: r_registers,
329 body: r_body,
330 returns: r_returns,
331 ..
332 },
333 ) => {
334 l_registers.eq(r_registers, ctx)
335 && l_body.clone() == r_body.clone()
336 && l_returns == r_returns
337 }
338 (
339 Self::StructFieldAccess {
340 prefix: l_prefix,
341 field_to_access: l_field_to_access,
342 resolved_type_of_parent: l_resolved_type_of_parent,
343 ..
344 },
345 Self::StructFieldAccess {
346 prefix: r_prefix,
347 field_to_access: r_field_to_access,
348 resolved_type_of_parent: r_resolved_type_of_parent,
349 ..
350 },
351 ) => {
352 (**l_prefix).eq(&**r_prefix, ctx)
353 && l_field_to_access.eq(r_field_to_access, ctx)
354 && type_engine
355 .get(*l_resolved_type_of_parent)
356 .eq(&type_engine.get(*r_resolved_type_of_parent), ctx)
357 }
358 (
359 Self::TupleElemAccess {
360 prefix: l_prefix,
361 elem_to_access_num: l_elem_to_access_num,
362 resolved_type_of_parent: l_resolved_type_of_parent,
363 ..
364 },
365 Self::TupleElemAccess {
366 prefix: r_prefix,
367 elem_to_access_num: r_elem_to_access_num,
368 resolved_type_of_parent: r_resolved_type_of_parent,
369 ..
370 },
371 ) => {
372 (**l_prefix).eq(&**r_prefix, ctx)
373 && l_elem_to_access_num == r_elem_to_access_num
374 && type_engine
375 .get(*l_resolved_type_of_parent)
376 .eq(&type_engine.get(*r_resolved_type_of_parent), ctx)
377 }
378 (
379 Self::EnumInstantiation {
380 enum_ref: l_enum_ref,
381 variant_name: l_variant_name,
382 tag: l_tag,
383 contents: l_contents,
384 ..
385 },
386 Self::EnumInstantiation {
387 enum_ref: r_enum_ref,
388 variant_name: r_variant_name,
389 tag: r_tag,
390 contents: r_contents,
391 ..
392 },
393 ) => {
394 l_enum_ref.eq(r_enum_ref, ctx)
395 && l_variant_name == r_variant_name
396 && l_tag == r_tag
397 && if let (Some(l_contents), Some(r_contents)) = (l_contents, r_contents) {
398 (**l_contents).eq(&**r_contents, ctx)
399 } else {
400 true
401 }
402 }
403 (
404 Self::AbiCast {
405 abi_name: l_abi_name,
406 address: l_address,
407 ..
408 },
409 Self::AbiCast {
410 abi_name: r_abi_name,
411 address: r_address,
412 ..
413 },
414 ) => l_abi_name == r_abi_name && (**l_address).eq(&**r_address, ctx),
415 (Self::IntrinsicFunction(l_kind), Self::IntrinsicFunction(r_kind)) => {
416 l_kind.eq(r_kind, ctx)
417 }
418 (
419 Self::UnsafeDowncast {
420 exp: l_exp,
421 variant: l_variant,
422 call_path_decl: _,
423 },
424 Self::UnsafeDowncast {
425 exp: r_exp,
426 variant: r_variant,
427 call_path_decl: _,
428 },
429 ) => l_exp.eq(r_exp, ctx) && l_variant.eq(r_variant, ctx),
430 (Self::EnumTag { exp: l_exp }, Self::EnumTag { exp: r_exp }) => l_exp.eq(r_exp, ctx),
431 (Self::StorageAccess(l_exp), Self::StorageAccess(r_exp)) => l_exp.eq(r_exp, ctx),
432 (
433 Self::WhileLoop {
434 body: l_body,
435 condition: l_condition,
436 },
437 Self::WhileLoop {
438 body: r_body,
439 condition: r_condition,
440 },
441 ) => l_body.eq(r_body, ctx) && l_condition.eq(r_condition, ctx),
442 (l, r) => std::mem::discriminant(l) == std::mem::discriminant(r),
443 }
444 }
445}
446
447impl HashWithEngines for TyExpressionVariant {
448 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
449 let type_engine = engines.te();
450 std::mem::discriminant(self).hash(state);
451 match self {
452 Self::Literal(lit) => {
453 lit.hash(state);
454 }
455 Self::FunctionApplication {
456 call_path,
457 arguments,
458 fn_ref,
459 contract_call_params: _,
462 selector: _,
463 type_binding: _,
464 call_path_typeid: _,
465 ..
466 } => {
467 call_path.hash(state);
468 fn_ref.hash(state, engines);
469 arguments.iter().for_each(|(name, arg)| {
470 name.hash(state);
471 arg.hash(state, engines);
472 });
473 }
474 Self::LazyOperator { op, lhs, rhs } => {
475 op.hash(state);
476 lhs.hash(state, engines);
477 rhs.hash(state, engines);
478 }
479 Self::ConstantExpression {
480 decl: const_decl,
481 span: _,
482 call_path: _,
483 } => {
484 const_decl.hash(state, engines);
485 }
486 Self::ConfigurableExpression {
487 decl: const_decl,
488 span: _,
489 call_path: _,
490 } => {
491 const_decl.hash(state, engines);
492 }
493 Self::ConstGenericExpression {
494 decl: const_generic_decl,
495 span: _,
496 call_path: _,
497 } => {
498 const_generic_decl.name().hash(state);
499 }
500 Self::VariableExpression {
501 name,
502 mutability,
503 call_path: _,
506 span: _,
507 } => {
508 name.hash(state);
509 mutability.hash(state);
510 }
511 Self::Tuple { fields } => {
512 fields.hash(state, engines);
513 }
514 Self::ArrayExplicit {
515 contents,
516 elem_type: _,
517 } => {
518 contents.hash(state, engines);
519 }
520 Self::ArrayRepeat {
521 value,
522 length,
523 elem_type: _,
524 } => {
525 value.hash(state, engines);
526 length.hash(state, engines);
527 }
528 Self::ArrayIndex { prefix, index } => {
529 prefix.hash(state, engines);
530 index.hash(state, engines);
531 }
532 Self::StructExpression {
533 struct_id,
534 fields,
535 instantiation_span: _,
538 call_path_binding: _,
539 } => {
540 HashWithEngines::hash(&struct_id, state, engines);
541 fields.hash(state, engines);
542 }
543 Self::CodeBlock(contents) => {
544 contents.hash(state, engines);
545 }
546 Self::MatchExp {
547 desugared,
548 scrutinees: _,
551 } => {
552 desugared.hash(state, engines);
553 }
554 Self::IfExp {
555 condition,
556 then,
557 r#else,
558 } => {
559 condition.hash(state, engines);
560 then.hash(state, engines);
561 if let Some(x) = r#else.as_ref() {
562 x.hash(state, engines)
563 }
564 }
565 Self::AsmExpression {
566 registers,
567 body,
568 returns,
569 whole_block_span: _,
572 } => {
573 registers.hash(state, engines);
574 body.hash(state);
575 returns.hash(state);
576 }
577 Self::StructFieldAccess {
578 prefix,
579 field_to_access,
580 resolved_type_of_parent,
581 field_instantiation_span: _,
584 } => {
585 prefix.hash(state, engines);
586 field_to_access.hash(state, engines);
587 type_engine
588 .get(*resolved_type_of_parent)
589 .hash(state, engines);
590 }
591 Self::TupleElemAccess {
592 prefix,
593 elem_to_access_num,
594 resolved_type_of_parent,
595 elem_to_access_span: _,
598 } => {
599 prefix.hash(state, engines);
600 elem_to_access_num.hash(state);
601 type_engine
602 .get(*resolved_type_of_parent)
603 .hash(state, engines);
604 }
605 Self::EnumInstantiation {
606 enum_ref,
607 variant_name,
608 tag,
609 contents,
610 variant_instantiation_span: _,
613 call_path_binding: _,
614 call_path_decl: _,
615 } => {
616 enum_ref.hash(state, engines);
617 variant_name.hash(state);
618 tag.hash(state);
619 if let Some(x) = contents.as_ref() {
620 x.hash(state, engines)
621 }
622 }
623 Self::AbiCast {
624 abi_name,
625 address,
626 span: _,
629 } => {
630 abi_name.hash(state);
631 address.hash(state, engines);
632 }
633 Self::StorageAccess(exp) => {
634 exp.hash(state, engines);
635 }
636 Self::IntrinsicFunction(exp) => {
637 exp.hash(state, engines);
638 }
639 Self::AbiName(name) => {
640 name.hash(state);
641 }
642 Self::EnumTag { exp } => {
643 exp.hash(state, engines);
644 }
645 Self::UnsafeDowncast {
646 exp,
647 variant,
648 call_path_decl: _,
649 } => {
650 exp.hash(state, engines);
651 variant.hash(state, engines);
652 }
653 Self::WhileLoop { condition, body } => {
654 condition.hash(state, engines);
655 body.hash(state, engines);
656 }
657 Self::ForLoop { desugared } => {
658 desugared.hash(state, engines);
659 }
660 Self::Break | Self::Continue | Self::FunctionParameter => {}
661 Self::Reassignment(exp) => {
662 exp.hash(state, engines);
663 }
664 Self::ImplicitReturn(exp) | Self::Return(exp) => {
665 exp.hash(state, engines);
666 }
667 Self::Ref(exp) | Self::Deref(exp) => {
668 exp.hash(state, engines);
669 }
670 }
671 }
672}
673
674impl SubstTypes for TyExpressionVariant {
675 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
676 use TyExpressionVariant::*;
677 match self {
678 Literal(..) => HasChanges::No,
679 FunctionApplication {
680 arguments,
681 ref mut fn_ref,
682 ref mut call_path_typeid,
683 ..
684 } => has_changes! {
685 arguments.subst(ctx);
686 if let Some(new_decl_ref) = fn_ref
687 .clone()
688 .subst_types_and_insert_new_with_parent(ctx)
689 {
690 fn_ref.replace_id(*new_decl_ref.id());
691 HasChanges::Yes
692 } else {
693 HasChanges::No
694 };
695 call_path_typeid.subst(ctx);
696 },
697 LazyOperator { lhs, rhs, .. } => has_changes! {
698 lhs.subst(ctx);
699 rhs.subst(ctx);
700 },
701 ConstantExpression { decl, .. } => decl.subst(ctx),
702 ConfigurableExpression { decl, .. } => decl.subst(ctx),
703 ConstGenericExpression { decl, .. } => decl.subst(ctx),
704 VariableExpression { .. } => HasChanges::No,
705 Tuple { fields } => fields.subst(ctx),
706 ArrayExplicit {
707 ref mut elem_type,
708 contents,
709 } => has_changes! {
710 elem_type.subst(ctx);
711 contents.subst(ctx);
712 },
713 ArrayRepeat {
714 ref mut elem_type,
715 value,
716 length,
717 } => has_changes! {
718 elem_type.subst(ctx);
719 value.subst(ctx);
720 length.subst(ctx);
721 },
722 ArrayIndex { prefix, index } => has_changes! {
723 prefix.subst(ctx);
724 index.subst(ctx);
725 },
726 StructExpression {
727 struct_id,
728 fields,
729 instantiation_span: _,
730 call_path_binding: _,
731 } => has_changes! {
732 if let Some(new_struct_ref) = struct_id
733 .clone()
734 .subst_types_and_insert_new(ctx) {
735 struct_id.replace_id(*new_struct_ref.id());
736 HasChanges::Yes
737 } else {
738 HasChanges::No
739 };
740 fields.subst(ctx);
741 },
742 CodeBlock(block) => block.subst(ctx),
743 FunctionParameter => HasChanges::No,
744 MatchExp { desugared, .. } => desugared.subst(ctx),
745 IfExp {
746 condition,
747 then,
748 r#else,
749 } => has_changes! {
750 condition.subst(ctx);
751 then.subst(ctx);
752 r#else.subst(ctx);
753 },
754 AsmExpression {
755 registers, ..
757 } => registers.subst(ctx),
758 StructFieldAccess {
761 prefix,
762 field_to_access,
763 ref mut resolved_type_of_parent,
764 ..
765 } => has_changes! {
766 resolved_type_of_parent.subst(ctx);
767 field_to_access.subst(ctx);
768 prefix.subst(ctx);
769 },
770 TupleElemAccess {
771 prefix,
772 ref mut resolved_type_of_parent,
773 ..
774 } => has_changes! {
775 resolved_type_of_parent.subst(ctx);
776 prefix.subst(ctx);
777 },
778 EnumInstantiation {
779 enum_ref, contents, ..
780 } => has_changes! {
781 if let Some(new_enum_ref) = enum_ref
782 .clone()
783 .subst_types_and_insert_new(ctx)
784 {
785 enum_ref.replace_id(*new_enum_ref.id());
786 HasChanges::Yes
787 } else {
788 HasChanges::No
789 };
790 contents.subst(ctx);
791 },
792 AbiCast { address, .. } => address.subst(ctx),
793 StorageAccess { .. } => HasChanges::No,
795 IntrinsicFunction(kind) => kind.subst(ctx),
796 EnumTag { exp } => exp.subst(ctx),
797 UnsafeDowncast {
798 exp,
799 variant,
800 call_path_decl: _,
801 } => has_changes! {
802 exp.subst(ctx);
803 variant.subst(ctx);
804 },
805 AbiName(_) => HasChanges::No,
806 WhileLoop {
807 ref mut condition,
808 ref mut body,
809 } => {
810 condition.subst(ctx);
811 body.subst(ctx)
812 }
813 ForLoop { ref mut desugared } => desugared.subst(ctx),
814 Break => HasChanges::No,
815 Continue => HasChanges::No,
816 Reassignment(reassignment) => reassignment.subst(ctx),
817 ImplicitReturn(expr) | Return(expr) => expr.subst(ctx),
818 Ref(exp) | Deref(exp) => exp.subst(ctx),
819 }
820 }
821}
822
823impl ReplaceDecls for TyExpressionVariant {
824 fn replace_decls_inner(
825 &mut self,
826 decl_mapping: &DeclMapping,
827 handler: &Handler,
828 ctx: &mut TypeCheckContext,
829 ) -> Result<bool, ErrorEmitted> {
830 handler.scope(|handler| {
831 use TyExpressionVariant::*;
832 match self {
833 Literal(..) => Ok(false),
834 FunctionApplication {
835 ref mut fn_ref,
836 ref mut arguments,
837 call_path,
838 ..
839 } => {
840 let mut has_changes = false;
841
842 has_changes |= fn_ref.replace_decls(decl_mapping, handler, ctx)?;
843
844 for (_, arg) in arguments.iter_mut() {
845 if let Ok(r) = arg.replace_decls(decl_mapping, handler, ctx) {
846 has_changes |= r;
847 }
848 }
849
850 let decl_engine = ctx.engines().de();
851 let mut method = (*decl_engine.get(fn_ref)).clone();
852
853 if method.is_trait_method_dummy {
858 if let Some(implementing_for_typeid) = method.implementing_for_typeid {
859 let implementing_type_method_ref = ctx.find_method_for_type(
860 handler,
861 implementing_for_typeid,
862 &[ctx.namespace().current_package_name().clone()],
863 &call_path.suffix,
864 method.return_type.type_id,
865 &arguments
866 .iter()
867 .map(|a| a.1.return_type)
868 .collect::<VecDeque<_>>(),
869 None,
870 )?;
871 method = (*decl_engine.get(&implementing_type_method_ref)).clone();
872 }
873 }
874
875 let mut inner_decl_mapping =
878 TypeParameter::gather_decl_mapping_from_trait_constraints(
879 handler,
880 ctx.by_ref(),
881 &method.type_parameters,
882 method.name.as_str(),
883 &method.name.span(),
884 )?;
885
886 inner_decl_mapping.extend(decl_mapping);
887
888 if method.replace_decls(&inner_decl_mapping, handler, ctx)? {
889 decl_engine.replace(*fn_ref.id(), method);
890 has_changes = true;
891 }
892
893 Ok(has_changes)
894 }
895 LazyOperator { lhs, rhs, .. } => {
896 let mut has_changes = (*lhs).replace_decls(decl_mapping, handler, ctx)?;
897 has_changes |= (*rhs).replace_decls(decl_mapping, handler, ctx)?;
898 Ok(has_changes)
899 }
900 ConstantExpression { decl, .. } => decl.replace_decls(decl_mapping, handler, ctx),
901 ConfigurableExpression { decl, .. } => {
902 decl.replace_decls(decl_mapping, handler, ctx)
903 }
904 ConstGenericExpression { .. } => Ok(false),
905 VariableExpression { .. } => Ok(false),
906 Tuple { fields } => {
907 let mut has_changes = false;
908 for item in fields.iter_mut() {
909 if let Ok(r) = item.replace_decls(decl_mapping, handler, ctx) {
910 has_changes |= r;
911 }
912 }
913 Ok(has_changes)
914 }
915 ArrayExplicit {
916 elem_type: _,
917 contents,
918 } => {
919 let mut has_changes = false;
920 for expr in contents.iter_mut() {
921 if let Ok(r) = expr.replace_decls(decl_mapping, handler, ctx) {
922 has_changes |= r;
923 }
924 }
925 Ok(has_changes)
926 }
927 ArrayRepeat {
928 elem_type: _,
929 value,
930 length,
931 } => {
932 let mut has_changes = (*value).replace_decls(decl_mapping, handler, ctx)?;
933 has_changes |= (*length).replace_decls(decl_mapping, handler, ctx)?;
934 Ok(has_changes)
935 }
936 ArrayIndex { prefix, index } => {
937 let mut has_changes = false;
938 if let Ok(r) = (*prefix).replace_decls(decl_mapping, handler, ctx) {
939 has_changes |= r;
940 }
941 if let Ok(r) = (*index).replace_decls(decl_mapping, handler, ctx) {
942 has_changes |= r;
943 }
944 Ok(has_changes)
945 }
946 StructExpression {
947 struct_id: _,
948 fields,
949 instantiation_span: _,
950 call_path_binding: _,
951 } => {
952 let mut has_changes = false;
953 for field in fields.iter_mut() {
954 if let Ok(r) = field.replace_decls(decl_mapping, handler, ctx) {
955 has_changes |= r;
956 }
957 }
958 Ok(has_changes)
959 }
960 CodeBlock(block) => block.replace_decls(decl_mapping, handler, ctx),
961 FunctionParameter => Ok(false),
962 MatchExp { desugared, .. } => desugared.replace_decls(decl_mapping, handler, ctx),
963 IfExp {
964 condition,
965 then,
966 r#else,
967 } => {
968 let mut has_changes = false;
969 if let Ok(r) = condition.replace_decls(decl_mapping, handler, ctx) {
970 has_changes |= r;
971 }
972 if let Ok(r) = then.replace_decls(decl_mapping, handler, ctx) {
973 has_changes |= r;
974 }
975 if let Some(r) = r#else
976 .as_mut()
977 .and_then(|expr| expr.replace_decls(decl_mapping, handler, ctx).ok())
978 {
979 has_changes |= r;
980 }
981 Ok(has_changes)
982 }
983 AsmExpression { .. } => Ok(false),
984 StructFieldAccess { prefix, .. } => {
985 prefix.replace_decls(decl_mapping, handler, ctx)
986 }
987 TupleElemAccess { prefix, .. } => prefix.replace_decls(decl_mapping, handler, ctx),
988 EnumInstantiation {
989 enum_ref: _,
990 contents,
991 ..
992 } => {
993 if let Some(ref mut contents) = contents {
996 contents.replace_decls(decl_mapping, handler, ctx)
997 } else {
998 Ok(false)
999 }
1000 }
1001 AbiCast { address, .. } => address.replace_decls(decl_mapping, handler, ctx),
1002 StorageAccess { .. } => Ok(false),
1003 IntrinsicFunction(TyIntrinsicFunctionKind { arguments, .. }) => {
1004 let mut has_changes = false;
1005 for expr in arguments.iter_mut() {
1006 if let Ok(r) = expr.replace_decls(decl_mapping, handler, ctx) {
1007 has_changes |= r;
1008 }
1009 }
1010 Ok(has_changes)
1011 }
1012 EnumTag { exp } => exp.replace_decls(decl_mapping, handler, ctx),
1013 UnsafeDowncast { exp, .. } => exp.replace_decls(decl_mapping, handler, ctx),
1014 AbiName(_) => Ok(false),
1015 WhileLoop {
1016 ref mut condition,
1017 ref mut body,
1018 } => {
1019 let mut has_changes = false;
1020 if let Ok(r) = condition.replace_decls(decl_mapping, handler, ctx) {
1021 has_changes |= r;
1022 }
1023 if let Ok(r) = body.replace_decls(decl_mapping, handler, ctx) {
1024 has_changes |= r;
1025 }
1026 Ok(has_changes)
1027 }
1028 ForLoop { ref mut desugared } => {
1029 desugared.replace_decls(decl_mapping, handler, ctx)
1030 }
1031 Break => Ok(false),
1032 Continue => Ok(false),
1033 Reassignment(reassignment) => {
1034 reassignment.replace_decls(decl_mapping, handler, ctx)
1035 }
1036 ImplicitReturn(expr) | Return(expr) => {
1037 expr.replace_decls(decl_mapping, handler, ctx)
1038 }
1039 Ref(exp) | Deref(exp) => exp.replace_decls(decl_mapping, handler, ctx),
1040 }
1041 })
1042 }
1043}
1044
1045impl TypeCheckAnalysis for TyExpressionVariant {
1046 fn type_check_analyze(
1047 &self,
1048 handler: &Handler,
1049 ctx: &mut TypeCheckAnalysisContext,
1050 ) -> Result<(), ErrorEmitted> {
1051 match self {
1052 TyExpressionVariant::Literal(_) => {}
1053 TyExpressionVariant::FunctionApplication {
1054 fn_ref, arguments, ..
1055 } => {
1056 let fn_decl_id = ctx.get_normalized_fn_node_id(fn_ref.id());
1057
1058 let fn_node = ctx.get_node_for_fn_decl(&fn_decl_id);
1059 if let Some(fn_node) = fn_node {
1060 ctx.add_edge_from_current(
1061 fn_node,
1062 TyNodeDepGraphEdge(TyNodeDepGraphEdgeInfo::FnApp),
1063 );
1064
1065 if !ctx.node_stack.contains(&fn_node) {
1066 let _ = fn_decl_id.type_check_analyze(handler, ctx);
1067 }
1068 }
1069
1070 let decl = ctx.engines.de().get(fn_ref.id());
1072
1073 use crate::type_system::unify::unifier::*;
1074 let unifier = Unifier::new(ctx.engines, "", UnifyKind::Default);
1075
1076 for (decl_param, arg) in decl.parameters.iter().zip(arguments.iter()) {
1077 unifier.unify(
1078 handler,
1079 arg.1.return_type,
1080 decl_param.type_argument.type_id,
1081 &Span::dummy(),
1082 false,
1083 );
1084 }
1085 }
1086 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
1087 lhs.type_check_analyze(handler, ctx)?;
1088 rhs.type_check_analyze(handler, ctx)?
1089 }
1090 TyExpressionVariant::ConstantExpression { decl, .. } => {
1091 decl.type_check_analyze(handler, ctx)?
1092 }
1093 TyExpressionVariant::ConfigurableExpression { decl, .. } => {
1094 decl.type_check_analyze(handler, ctx)?
1095 }
1096 TyExpressionVariant::ConstGenericExpression { decl, .. } => {
1097 decl.type_check_analyze(handler, ctx)?
1098 }
1099 TyExpressionVariant::VariableExpression { .. } => {}
1100 TyExpressionVariant::Tuple { fields } => {
1101 for field in fields.iter() {
1102 field.type_check_analyze(handler, ctx)?
1103 }
1104 }
1105 TyExpressionVariant::ArrayExplicit { contents, .. } => {
1106 for elem in contents.iter() {
1107 elem.type_check_analyze(handler, ctx)?
1108 }
1109 }
1110 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
1111 value.type_check_analyze(handler, ctx)?;
1112 length.type_check_analyze(handler, ctx)?;
1113 }
1114 TyExpressionVariant::ArrayIndex { prefix, index } => {
1115 prefix.type_check_analyze(handler, ctx)?;
1116 index.type_check_analyze(handler, ctx)?;
1117 }
1118 TyExpressionVariant::StructExpression { fields: _, .. } => {}
1119 TyExpressionVariant::CodeBlock(block) => {
1120 block.type_check_analyze(handler, ctx)?;
1121 }
1122 TyExpressionVariant::FunctionParameter => {}
1123 TyExpressionVariant::MatchExp {
1124 desugared,
1125 scrutinees: _,
1126 } => {
1127 desugared.type_check_analyze(handler, ctx)?;
1128 }
1129 TyExpressionVariant::IfExp {
1130 condition,
1131 then,
1132 r#else,
1133 } => {
1134 condition.type_check_analyze(handler, ctx)?;
1135 then.type_check_analyze(handler, ctx)?;
1136 if let Some(r#else) = r#else {
1137 r#else.type_check_analyze(handler, ctx)?;
1138 }
1139 }
1140 TyExpressionVariant::AsmExpression { .. } => {}
1141 TyExpressionVariant::StructFieldAccess { prefix, .. } => {
1142 prefix.type_check_analyze(handler, ctx)?;
1143 }
1144 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
1145 prefix.type_check_analyze(handler, ctx)?;
1146 }
1147 TyExpressionVariant::EnumInstantiation { contents, .. } => {
1148 for expr in contents.iter() {
1149 expr.type_check_analyze(handler, ctx)?
1150 }
1151 }
1152 TyExpressionVariant::AbiCast { address, .. } => {
1153 address.type_check_analyze(handler, ctx)?;
1154 }
1155 TyExpressionVariant::StorageAccess(_node) => {}
1156 TyExpressionVariant::IntrinsicFunction(node) => {
1157 for arg in node.arguments.iter() {
1158 arg.type_check_analyze(handler, ctx)?
1159 }
1160 }
1161 TyExpressionVariant::AbiName(_node) => {}
1162 TyExpressionVariant::EnumTag { exp } => {
1163 exp.type_check_analyze(handler, ctx)?;
1164 }
1165 TyExpressionVariant::UnsafeDowncast { exp, .. } => {
1166 exp.type_check_analyze(handler, ctx)?;
1167 }
1168 TyExpressionVariant::WhileLoop { condition, body } => {
1169 condition.type_check_analyze(handler, ctx)?;
1170 body.type_check_analyze(handler, ctx)?;
1171 }
1172 TyExpressionVariant::ForLoop { desugared } => {
1173 desugared.type_check_analyze(handler, ctx)?;
1174 }
1175 TyExpressionVariant::Break => {}
1176 TyExpressionVariant::Continue => {}
1177 TyExpressionVariant::Reassignment(node) => {
1178 node.type_check_analyze(handler, ctx)?;
1179 }
1180 TyExpressionVariant::ImplicitReturn(node) | TyExpressionVariant::Return(node) => {
1181 node.type_check_analyze(handler, ctx)?;
1182 }
1183 TyExpressionVariant::Ref(exp) | TyExpressionVariant::Deref(exp) => {
1184 exp.type_check_analyze(handler, ctx)?;
1185 }
1186 }
1187 Ok(())
1188 }
1189}
1190
1191impl TypeCheckFinalization for TyExpressionVariant {
1192 fn type_check_finalize(
1193 &mut self,
1194 handler: &Handler,
1195 ctx: &mut TypeCheckFinalizationContext,
1196 ) -> Result<(), ErrorEmitted> {
1197 handler.scope(|handler| {
1198 match self {
1199 TyExpressionVariant::ConstGenericExpression { .. } => {
1200 todo!("Will be implemented by https://github.com/FuelLabs/sway/issues/6860")
1201 }
1202 TyExpressionVariant::Literal(_) => {}
1203 TyExpressionVariant::FunctionApplication { arguments, .. } => {
1204 for (_, arg) in arguments.iter_mut() {
1205 let _ = arg.type_check_finalize(handler, ctx);
1206 }
1207 }
1208 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
1209 lhs.type_check_finalize(handler, ctx)?;
1210 rhs.type_check_finalize(handler, ctx)?
1211 }
1212 TyExpressionVariant::ConstantExpression { decl, .. } => {
1213 decl.type_check_finalize(handler, ctx)?
1214 }
1215 TyExpressionVariant::ConfigurableExpression { decl, .. } => {
1216 decl.type_check_finalize(handler, ctx)?
1217 }
1218 TyExpressionVariant::VariableExpression { .. } => {}
1219 TyExpressionVariant::Tuple { fields } => {
1220 for field in fields.iter_mut() {
1221 field.type_check_finalize(handler, ctx)?
1222 }
1223 }
1224 TyExpressionVariant::ArrayExplicit { contents, .. } => {
1225 for elem in contents.iter_mut() {
1226 elem.type_check_finalize(handler, ctx)?
1227 }
1228 }
1229 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
1230 value.type_check_finalize(handler, ctx)?;
1231 length.type_check_finalize(handler, ctx)?;
1232 }
1233 TyExpressionVariant::ArrayIndex { prefix, index } => {
1234 prefix.type_check_finalize(handler, ctx)?;
1235 index.type_check_finalize(handler, ctx)?;
1236 }
1237 TyExpressionVariant::StructExpression { fields, .. } => {
1238 for field in fields.iter_mut() {
1239 field.type_check_finalize(handler, ctx)?;
1240 }
1241 }
1242 TyExpressionVariant::CodeBlock(block) => {
1243 block.type_check_finalize(handler, ctx)?;
1244 }
1245 TyExpressionVariant::FunctionParameter => {}
1246 TyExpressionVariant::MatchExp {
1247 desugared,
1248 scrutinees,
1249 } => {
1250 desugared.type_check_finalize(handler, ctx)?;
1251 for scrutinee in scrutinees.iter_mut() {
1252 scrutinee.type_check_finalize(handler, ctx)?
1253 }
1254 }
1255 TyExpressionVariant::IfExp {
1256 condition,
1257 then,
1258 r#else,
1259 } => {
1260 condition.type_check_finalize(handler, ctx)?;
1261 then.type_check_finalize(handler, ctx)?;
1262 if let Some(ref mut r#else) = r#else {
1263 r#else.type_check_finalize(handler, ctx)?;
1264 }
1265 }
1266 TyExpressionVariant::AsmExpression { .. } => {}
1267 TyExpressionVariant::StructFieldAccess { prefix, .. } => {
1268 prefix.type_check_finalize(handler, ctx)?;
1269 }
1270 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
1271 prefix.type_check_finalize(handler, ctx)?;
1272 }
1273 TyExpressionVariant::EnumInstantiation { contents, .. } => {
1274 for expr in contents.iter_mut() {
1275 expr.type_check_finalize(handler, ctx)?
1276 }
1277 }
1278 TyExpressionVariant::AbiCast { address, .. } => {
1279 address.type_check_finalize(handler, ctx)?;
1280 }
1281 TyExpressionVariant::StorageAccess(_) => {
1282 todo!("")
1283 }
1284 TyExpressionVariant::IntrinsicFunction(kind) => {
1285 for expr in kind.arguments.iter_mut() {
1286 expr.type_check_finalize(handler, ctx)?;
1287 }
1288 }
1289 TyExpressionVariant::AbiName(_) => {
1290 todo!("")
1291 }
1292 TyExpressionVariant::EnumTag { exp } => {
1293 exp.type_check_finalize(handler, ctx)?;
1294 }
1295 TyExpressionVariant::UnsafeDowncast { exp, .. } => {
1296 exp.type_check_finalize(handler, ctx)?;
1297 }
1298 TyExpressionVariant::WhileLoop { condition, body } => {
1299 condition.type_check_finalize(handler, ctx)?;
1300 body.type_check_finalize(handler, ctx)?;
1301 }
1302 TyExpressionVariant::ForLoop { desugared } => {
1303 desugared.type_check_finalize(handler, ctx)?;
1304 }
1305 TyExpressionVariant::Break => {}
1306 TyExpressionVariant::Continue => {}
1307 TyExpressionVariant::Reassignment(node) => {
1308 node.type_check_finalize(handler, ctx)?;
1309 }
1310 TyExpressionVariant::ImplicitReturn(node) | TyExpressionVariant::Return(node) => {
1311 node.type_check_finalize(handler, ctx)?;
1312 }
1313 TyExpressionVariant::Ref(exp) | TyExpressionVariant::Deref(exp) => {
1314 exp.type_check_finalize(handler, ctx)?;
1315 }
1316 }
1317 Ok(())
1318 })
1319 }
1320}
1321
1322impl UpdateConstantExpression for TyExpressionVariant {
1323 fn update_constant_expression(&mut self, engines: &Engines, implementing_type: &TyDecl) {
1324 use TyExpressionVariant::*;
1325 match self {
1326 Literal(..) => (),
1327 FunctionApplication { .. } => (),
1328 LazyOperator { lhs, rhs, .. } => {
1329 (*lhs).update_constant_expression(engines, implementing_type);
1330 (*rhs).update_constant_expression(engines, implementing_type);
1331 }
1332 ConstantExpression { ref mut decl, .. } => {
1333 if let Some(impl_const) =
1334 find_const_decl_from_impl(implementing_type, engines.de(), decl)
1335 {
1336 *decl = Box::new(impl_const);
1337 }
1338 }
1339 ConfigurableExpression { .. } => {
1340 unreachable!()
1341 }
1342 ConstGenericExpression { .. } => {}
1343 VariableExpression { .. } => (),
1344 Tuple { fields } => fields
1345 .iter_mut()
1346 .for_each(|x| x.update_constant_expression(engines, implementing_type)),
1347 ArrayExplicit {
1348 contents,
1349 elem_type: _,
1350 } => contents
1351 .iter_mut()
1352 .for_each(|x| x.update_constant_expression(engines, implementing_type)),
1353 ArrayRepeat {
1354 elem_type: _,
1355 value,
1356 length,
1357 } => {
1358 value.update_constant_expression(engines, implementing_type);
1359 length.update_constant_expression(engines, implementing_type);
1360 }
1361 ArrayIndex { prefix, index } => {
1362 (*prefix).update_constant_expression(engines, implementing_type);
1363 (*index).update_constant_expression(engines, implementing_type);
1364 }
1365 StructExpression { fields, .. } => fields.iter_mut().for_each(|x| {
1366 x.value
1367 .update_constant_expression(engines, implementing_type)
1368 }),
1369 CodeBlock(block) => {
1370 block.update_constant_expression(engines, implementing_type);
1371 }
1372 FunctionParameter => (),
1373 MatchExp { desugared, .. } => {
1374 desugared.update_constant_expression(engines, implementing_type)
1375 }
1376 IfExp {
1377 condition,
1378 then,
1379 r#else,
1380 } => {
1381 condition.update_constant_expression(engines, implementing_type);
1382 then.update_constant_expression(engines, implementing_type);
1383 if let Some(ref mut r#else) = r#else {
1384 r#else.update_constant_expression(engines, implementing_type);
1385 }
1386 }
1387 AsmExpression { .. } => {}
1388 StructFieldAccess { prefix, .. } => {
1389 prefix.update_constant_expression(engines, implementing_type);
1390 }
1391 TupleElemAccess { prefix, .. } => {
1392 prefix.update_constant_expression(engines, implementing_type);
1393 }
1394 EnumInstantiation {
1395 enum_ref: _,
1396 contents,
1397 ..
1398 } => {
1399 if let Some(ref mut contents) = contents {
1400 contents.update_constant_expression(engines, implementing_type);
1401 };
1402 }
1403 AbiCast { address, .. } => {
1404 address.update_constant_expression(engines, implementing_type)
1405 }
1406 StorageAccess { .. } => (),
1407 IntrinsicFunction(_) => {}
1408 EnumTag { exp } => {
1409 exp.update_constant_expression(engines, implementing_type);
1410 }
1411 UnsafeDowncast { exp, .. } => {
1412 exp.update_constant_expression(engines, implementing_type);
1413 }
1414 AbiName(_) => (),
1415 WhileLoop {
1416 ref mut condition,
1417 ref mut body,
1418 } => {
1419 condition.update_constant_expression(engines, implementing_type);
1420 body.update_constant_expression(engines, implementing_type);
1421 }
1422 ForLoop { ref mut desugared } => {
1423 desugared.update_constant_expression(engines, implementing_type);
1424 }
1425 Break => (),
1426 Continue => (),
1427 Reassignment(reassignment) => {
1428 reassignment.update_constant_expression(engines, implementing_type)
1429 }
1430 ImplicitReturn(expr) | Return(expr) => {
1431 expr.update_constant_expression(engines, implementing_type)
1432 }
1433 Ref(exp) | Deref(exp) => exp.update_constant_expression(engines, implementing_type),
1434 }
1435 }
1436}
1437
1438fn find_const_decl_from_impl(
1439 implementing_type: &TyDecl,
1440 decl_engine: &DeclEngine,
1441 const_decl: &TyConstantDecl,
1442) -> Option<TyConstantDecl> {
1443 match implementing_type {
1444 TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id, .. }) => {
1445 let impl_trait = decl_engine.get_impl_self_or_trait(&decl_id.clone());
1446 impl_trait
1447 .items
1448 .iter()
1449 .find(|item| match item {
1450 TyTraitItem::Constant(decl_id) => {
1451 let trait_const_decl =
1452 (*decl_engine.get_constant(&decl_id.clone())).clone();
1453 const_decl.name().eq(trait_const_decl.name())
1454 }
1455 _ => false,
1456 })
1457 .map(|item| match item {
1458 TyTraitItem::Constant(decl_id) => (*decl_engine.get_constant(decl_id)).clone(),
1459 _ => unreachable!(),
1460 })
1461 }
1462 TyDecl::AbiDecl(AbiDecl {
1463 decl_id: _decl_id, ..
1464 }) => todo!(""),
1465 _ => unreachable!(),
1466 }
1467}
1468
1469impl DisplayWithEngines for TyExpressionVariant {
1470 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
1471 DebugWithEngines::fmt(self, f, engines)
1473 }
1474}
1475
1476impl DebugWithEngines for TyExpressionVariant {
1477 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
1478 let s = match self {
1479 TyExpressionVariant::ConstGenericExpression { .. } => {
1480 todo!("Will be implemented by https://github.com/FuelLabs/sway/issues/6860")
1481 }
1482 TyExpressionVariant::Literal(lit) => format!("literal {lit}"),
1483 TyExpressionVariant::FunctionApplication {
1484 call_path: name, ..
1485 } => {
1486 format!("\"{}\" fn entry", name.suffix.as_str())
1487 }
1488 TyExpressionVariant::LazyOperator { op, .. } => match op {
1489 LazyOp::And => "&&".into(),
1490 LazyOp::Or => "||".into(),
1491 },
1492 TyExpressionVariant::Tuple { fields } => {
1493 let fields = fields
1494 .iter()
1495 .map(|field| format!("{:?}", engines.help_out(field)))
1496 .collect::<Vec<_>>()
1497 .join(", ");
1498 format!("tuple({fields})")
1499 }
1500 TyExpressionVariant::ArrayExplicit { .. } | TyExpressionVariant::ArrayRepeat { .. } => {
1501 "array".into()
1502 }
1503 TyExpressionVariant::ArrayIndex { .. } => "[..]".into(),
1504 TyExpressionVariant::StructExpression { struct_id, .. } => {
1505 let decl = engines.de().get(struct_id);
1506 format!("\"{}\" struct init", decl.name().as_str())
1507 }
1508 TyExpressionVariant::CodeBlock(_) => "code block entry".into(),
1509 TyExpressionVariant::FunctionParameter => "fn param access".into(),
1510 TyExpressionVariant::MatchExp { .. } | TyExpressionVariant::IfExp { .. } => {
1511 "if exp".into()
1512 }
1513 TyExpressionVariant::AsmExpression { .. } => "inline asm".into(),
1514 TyExpressionVariant::AbiCast { abi_name, .. } => {
1515 format!("abi cast {}", abi_name.suffix.as_str())
1516 }
1517 TyExpressionVariant::StructFieldAccess {
1518 resolved_type_of_parent,
1519 field_to_access,
1520 ..
1521 } => {
1522 format!(
1523 "\"{:?}.{}\" struct field access",
1524 engines.help_out(*resolved_type_of_parent),
1525 field_to_access.name
1526 )
1527 }
1528 TyExpressionVariant::TupleElemAccess {
1529 resolved_type_of_parent,
1530 elem_to_access_num,
1531 ..
1532 } => {
1533 format!(
1534 "\"{:?}.{}\" tuple index",
1535 engines.help_out(*resolved_type_of_parent),
1536 elem_to_access_num
1537 )
1538 }
1539 TyExpressionVariant::ConstantExpression { decl, .. } => {
1540 format!("\"{}\" constant exp", decl.name().as_str())
1541 }
1542 TyExpressionVariant::ConfigurableExpression { decl, .. } => {
1543 format!("\"{}\" configurable exp", decl.name().as_str())
1544 }
1545 TyExpressionVariant::VariableExpression { name, .. } => {
1546 format!("\"{}\" variable exp", name.as_str())
1547 }
1548 TyExpressionVariant::EnumInstantiation {
1549 tag,
1550 enum_ref,
1551 variant_name,
1552 ..
1553 } => {
1554 format!(
1555 "{}::{} enum instantiation (tag: {})",
1556 enum_ref.name().as_str(),
1557 variant_name.as_str(),
1558 tag
1559 )
1560 }
1561 TyExpressionVariant::StorageAccess(access) => {
1562 format!("storage field {} access", access.storage_field_name())
1563 }
1564 TyExpressionVariant::IntrinsicFunction(kind) => format!("{:?}", engines.help_out(kind)),
1565 TyExpressionVariant::AbiName(n) => format!("ABI name {n}"),
1566 TyExpressionVariant::EnumTag { exp } => {
1567 format!("({:?} as tag)", engines.help_out(exp.return_type))
1568 }
1569 TyExpressionVariant::UnsafeDowncast {
1570 exp,
1571 variant,
1572 call_path_decl,
1573 } => {
1574 format!(
1575 "({:?} as {}::{})",
1576 engines.help_out(exp.return_type),
1577 engines.help_out(call_path_decl),
1578 variant.name
1579 )
1580 }
1581 TyExpressionVariant::WhileLoop { condition, .. } => {
1582 format!("while loop on {:?}", engines.help_out(&**condition))
1583 }
1584 TyExpressionVariant::ForLoop { .. } => "for loop".to_string(),
1585 TyExpressionVariant::Break => "break".to_string(),
1586 TyExpressionVariant::Continue => "continue".to_string(),
1587 TyExpressionVariant::Reassignment(reassignment) => {
1588 let target = match &reassignment.lhs {
1589 TyReassignmentTarget::Deref(exp) => format!("{:?}", engines.help_out(exp)),
1590 TyReassignmentTarget::ElementAccess {
1591 base_name,
1592 base_type: _,
1593 indices,
1594 } => {
1595 let mut target = base_name.to_string();
1596 for index in indices {
1597 match index {
1598 ProjectionKind::StructField { name } => {
1599 target.push('.');
1600 target.push_str(name.as_str());
1601 }
1602 ProjectionKind::TupleField { index, .. } => {
1603 target.push('.');
1604 target.push_str(index.to_string().as_str());
1605 }
1606 ProjectionKind::ArrayIndex { index, .. } => {
1607 write!(&mut target, "[{:?}]", engines.help_out(index)).unwrap();
1608 }
1609 }
1610 }
1611 target
1612 }
1613 };
1614
1615 format!(
1616 "reassignment to {target} = {:?}",
1617 engines.help_out(&reassignment.rhs)
1618 )
1619 }
1620 TyExpressionVariant::ImplicitReturn(exp) => {
1621 format!("implicit return {:?}", engines.help_out(&**exp))
1622 }
1623 TyExpressionVariant::Return(exp) => {
1624 format!("return {:?}", engines.help_out(&**exp))
1625 }
1626 TyExpressionVariant::Ref(exp) => {
1627 format!("&({:?})", engines.help_out(&**exp))
1628 }
1629 TyExpressionVariant::Deref(exp) => {
1630 format!("*({:?})", engines.help_out(&**exp))
1631 }
1632 };
1633 write!(f, "{s}")
1634 }
1635}
1636
1637impl TyExpressionVariant {
1638 pub(crate) fn extract_literal_value(&self) -> Option<Literal> {
1640 match self {
1641 TyExpressionVariant::Literal(value) => Some(value.clone()),
1642 _ => None,
1643 }
1644 }
1645}