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