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 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: 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 Panic(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::Panic(exp) => {
669 exp.hash(state, engines);
670 }
671 Self::Ref(exp) | Self::Deref(exp) => {
672 exp.hash(state, engines);
673 }
674 }
675 }
676}
677
678impl SubstTypes for TyExpressionVariant {
679 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
680 use TyExpressionVariant::*;
681 match self {
682 Literal(..) => HasChanges::No,
683 FunctionApplication {
684 arguments,
685 ref mut fn_ref,
686 ref mut call_path_typeid,
687 ..
688 } => has_changes! {
689 arguments.subst(ctx);
690 if let Some(new_decl_ref) = fn_ref
691 .clone()
692 .subst_types_and_insert_new_with_parent(ctx)
693 {
694 fn_ref.replace_id(*new_decl_ref.id());
695 HasChanges::Yes
696 } else {
697 HasChanges::No
698 };
699 call_path_typeid.subst(ctx);
700 },
701 LazyOperator { lhs, rhs, .. } => has_changes! {
702 lhs.subst(ctx);
703 rhs.subst(ctx);
704 },
705 ConstantExpression { decl, .. } => decl.subst(ctx),
706 ConfigurableExpression { decl, .. } => decl.subst(ctx),
707 ConstGenericExpression { decl, .. } => decl.subst(ctx),
708 VariableExpression { .. } => HasChanges::No,
709 Tuple { fields } => fields.subst(ctx),
710 ArrayExplicit {
711 ref mut elem_type,
712 contents,
713 } => has_changes! {
714 elem_type.subst(ctx);
715 contents.subst(ctx);
716 },
717 ArrayRepeat {
718 ref mut elem_type,
719 value,
720 length,
721 } => has_changes! {
722 elem_type.subst(ctx);
723 value.subst(ctx);
724 length.subst(ctx);
725 },
726 ArrayIndex { prefix, index } => has_changes! {
727 prefix.subst(ctx);
728 index.subst(ctx);
729 },
730 StructExpression {
731 struct_id,
732 fields,
733 instantiation_span: _,
734 call_path_binding: _,
735 } => has_changes! {
736 if let Some(new_struct_ref) = struct_id
737 .clone()
738 .subst_types_and_insert_new(ctx) {
739 struct_id.replace_id(*new_struct_ref.id());
740 HasChanges::Yes
741 } else {
742 HasChanges::No
743 };
744 fields.subst(ctx);
745 },
746 CodeBlock(block) => block.subst(ctx),
747 FunctionParameter => HasChanges::No,
748 MatchExp { desugared, .. } => desugared.subst(ctx),
749 IfExp {
750 condition,
751 then,
752 r#else,
753 } => has_changes! {
754 condition.subst(ctx);
755 then.subst(ctx);
756 r#else.subst(ctx);
757 },
758 AsmExpression {
759 registers, ..
761 } => registers.subst(ctx),
762 StructFieldAccess {
765 prefix,
766 field_to_access,
767 ref mut resolved_type_of_parent,
768 ..
769 } => has_changes! {
770 resolved_type_of_parent.subst(ctx);
771 field_to_access.subst(ctx);
772 prefix.subst(ctx);
773 },
774 TupleElemAccess {
775 prefix,
776 ref mut resolved_type_of_parent,
777 ..
778 } => has_changes! {
779 resolved_type_of_parent.subst(ctx);
780 prefix.subst(ctx);
781 },
782 EnumInstantiation {
783 enum_ref, contents, ..
784 } => has_changes! {
785 if let Some(new_enum_ref) = enum_ref
786 .clone()
787 .subst_types_and_insert_new(ctx)
788 {
789 enum_ref.replace_id(*new_enum_ref.id());
790 HasChanges::Yes
791 } else {
792 HasChanges::No
793 };
794 contents.subst(ctx);
795 },
796 AbiCast { address, .. } => address.subst(ctx),
797 StorageAccess { .. } => HasChanges::No,
799 IntrinsicFunction(kind) => kind.subst(ctx),
800 EnumTag { exp } => exp.subst(ctx),
801 UnsafeDowncast {
802 exp,
803 variant,
804 call_path_decl: _,
805 } => has_changes! {
806 exp.subst(ctx);
807 variant.subst(ctx);
808 },
809 AbiName(_) => HasChanges::No,
810 WhileLoop {
811 ref mut condition,
812 ref mut body,
813 } => {
814 condition.subst(ctx);
815 body.subst(ctx)
816 }
817 ForLoop { ref mut desugared } => desugared.subst(ctx),
818 Break => HasChanges::No,
819 Continue => HasChanges::No,
820 Reassignment(reassignment) => reassignment.subst(ctx),
821 ImplicitReturn(expr) | Return(expr) => expr.subst(ctx),
822 Panic(expr) => expr.subst(ctx),
823 Ref(exp) | Deref(exp) => exp.subst(ctx),
824 }
825 }
826}
827
828impl ReplaceDecls for TyExpressionVariant {
829 fn replace_decls_inner(
830 &mut self,
831 decl_mapping: &DeclMapping,
832 handler: &Handler,
833 ctx: &mut TypeCheckContext,
834 ) -> Result<bool, ErrorEmitted> {
835 handler.scope(|handler| {
836 use TyExpressionVariant::*;
837 match self {
838 Literal(..) => Ok(false),
839 FunctionApplication {
840 ref mut fn_ref,
841 ref mut arguments,
842 call_path,
843 ..
844 } => {
845 let mut has_changes = false;
846
847 has_changes |= fn_ref.replace_decls(decl_mapping, handler, ctx)?;
848
849 for (_, arg) in arguments.iter_mut() {
850 if let Ok(r) = arg.replace_decls(decl_mapping, handler, ctx) {
851 has_changes |= r;
852 }
853 }
854
855 let decl_engine = ctx.engines().de();
856 let mut method = (*decl_engine.get(fn_ref)).clone();
857
858 if method.is_trait_method_dummy {
863 if let Some(implementing_for_typeid) = method.implementing_for_typeid {
864 let arguments_types = arguments
865 .iter()
866 .map(|a| a.1.return_type)
867 .collect::<Vec<_>>();
868 let implementing_type_method_ref = ctx.find_method_for_type(
869 handler,
870 implementing_for_typeid,
871 &[ctx.namespace().current_package_name().clone()],
872 &call_path.suffix,
873 method.return_type.type_id(),
874 &arguments_types,
875 None,
876 )?;
877 method = (*decl_engine.get(&implementing_type_method_ref)).clone();
878 }
879 }
880
881 let mut inner_decl_mapping =
884 GenericTypeParameter::gather_decl_mapping_from_trait_constraints(
885 handler,
886 ctx.by_ref(),
887 &method.type_parameters,
888 method.name.as_str(),
889 &method.name.span(),
890 )?;
891
892 inner_decl_mapping.extend(decl_mapping);
893
894 if method.replace_decls(&inner_decl_mapping, handler, ctx)? {
895 decl_engine.replace(*fn_ref.id(), method);
896 has_changes = true;
897 }
898
899 Ok(has_changes)
900 }
901 LazyOperator { lhs, rhs, .. } => {
902 let mut has_changes = (*lhs).replace_decls(decl_mapping, handler, ctx)?;
903 has_changes |= (*rhs).replace_decls(decl_mapping, handler, ctx)?;
904 Ok(has_changes)
905 }
906 ConstantExpression { decl, .. } => decl.replace_decls(decl_mapping, handler, ctx),
907 ConfigurableExpression { decl, .. } => {
908 decl.replace_decls(decl_mapping, handler, ctx)
909 }
910 ConstGenericExpression { .. } => Ok(false),
911 VariableExpression { .. } => Ok(false),
912 Tuple { fields } => {
913 let mut has_changes = false;
914 for item in fields.iter_mut() {
915 if let Ok(r) = item.replace_decls(decl_mapping, handler, ctx) {
916 has_changes |= r;
917 }
918 }
919 Ok(has_changes)
920 }
921 ArrayExplicit {
922 elem_type: _,
923 contents,
924 } => {
925 let mut has_changes = false;
926 for expr in contents.iter_mut() {
927 if let Ok(r) = expr.replace_decls(decl_mapping, handler, ctx) {
928 has_changes |= r;
929 }
930 }
931 Ok(has_changes)
932 }
933 ArrayRepeat {
934 elem_type: _,
935 value,
936 length,
937 } => {
938 let mut has_changes = (*value).replace_decls(decl_mapping, handler, ctx)?;
939 has_changes |= (*length).replace_decls(decl_mapping, handler, ctx)?;
940 Ok(has_changes)
941 }
942 ArrayIndex { prefix, index } => {
943 let mut has_changes = false;
944 if let Ok(r) = (*prefix).replace_decls(decl_mapping, handler, ctx) {
945 has_changes |= r;
946 }
947 if let Ok(r) = (*index).replace_decls(decl_mapping, handler, ctx) {
948 has_changes |= r;
949 }
950 Ok(has_changes)
951 }
952 StructExpression {
953 struct_id: _,
954 fields,
955 instantiation_span: _,
956 call_path_binding: _,
957 } => {
958 let mut has_changes = false;
959 for field in fields.iter_mut() {
960 if let Ok(r) = field.replace_decls(decl_mapping, handler, ctx) {
961 has_changes |= r;
962 }
963 }
964 Ok(has_changes)
965 }
966 CodeBlock(block) => block.replace_decls(decl_mapping, handler, ctx),
967 FunctionParameter => Ok(false),
968 MatchExp { desugared, .. } => desugared.replace_decls(decl_mapping, handler, ctx),
969 IfExp {
970 condition,
971 then,
972 r#else,
973 } => {
974 let mut has_changes = false;
975 if let Ok(r) = condition.replace_decls(decl_mapping, handler, ctx) {
976 has_changes |= r;
977 }
978 if let Ok(r) = then.replace_decls(decl_mapping, handler, ctx) {
979 has_changes |= r;
980 }
981 if let Some(r) = r#else
982 .as_mut()
983 .and_then(|expr| expr.replace_decls(decl_mapping, handler, ctx).ok())
984 {
985 has_changes |= r;
986 }
987 Ok(has_changes)
988 }
989 AsmExpression { .. } => Ok(false),
990 StructFieldAccess { prefix, .. } => {
991 prefix.replace_decls(decl_mapping, handler, ctx)
992 }
993 TupleElemAccess { prefix, .. } => prefix.replace_decls(decl_mapping, handler, ctx),
994 EnumInstantiation {
995 enum_ref: _,
996 contents,
997 ..
998 } => {
999 if let Some(ref mut contents) = contents {
1002 contents.replace_decls(decl_mapping, handler, ctx)
1003 } else {
1004 Ok(false)
1005 }
1006 }
1007 AbiCast { address, .. } => address.replace_decls(decl_mapping, handler, ctx),
1008 StorageAccess { .. } => Ok(false),
1009 IntrinsicFunction(TyIntrinsicFunctionKind { arguments, .. }) => {
1010 let mut has_changes = false;
1011 for expr in arguments.iter_mut() {
1012 if let Ok(r) = expr.replace_decls(decl_mapping, handler, ctx) {
1013 has_changes |= r;
1014 }
1015 }
1016 Ok(has_changes)
1017 }
1018 EnumTag { exp } => exp.replace_decls(decl_mapping, handler, ctx),
1019 UnsafeDowncast { exp, .. } => exp.replace_decls(decl_mapping, handler, ctx),
1020 AbiName(_) => Ok(false),
1021 WhileLoop {
1022 ref mut condition,
1023 ref mut body,
1024 } => {
1025 let mut has_changes = false;
1026 if let Ok(r) = condition.replace_decls(decl_mapping, handler, ctx) {
1027 has_changes |= r;
1028 }
1029 if let Ok(r) = body.replace_decls(decl_mapping, handler, ctx) {
1030 has_changes |= r;
1031 }
1032 Ok(has_changes)
1033 }
1034 ForLoop { ref mut desugared } => {
1035 desugared.replace_decls(decl_mapping, handler, ctx)
1036 }
1037 Break => Ok(false),
1038 Continue => Ok(false),
1039 Reassignment(reassignment) => {
1040 reassignment.replace_decls(decl_mapping, handler, ctx)
1041 }
1042 ImplicitReturn(expr) | Return(expr) => {
1043 expr.replace_decls(decl_mapping, handler, ctx)
1044 }
1045 Panic(expr) => expr.replace_decls(decl_mapping, handler, ctx),
1046 Ref(exp) | Deref(exp) => exp.replace_decls(decl_mapping, handler, ctx),
1047 }
1048 })
1049 }
1050}
1051
1052impl TypeCheckAnalysis for TyExpressionVariant {
1053 fn type_check_analyze(
1054 &self,
1055 handler: &Handler,
1056 ctx: &mut TypeCheckAnalysisContext,
1057 ) -> Result<(), ErrorEmitted> {
1058 match self {
1059 TyExpressionVariant::Literal(_) => {}
1060 TyExpressionVariant::FunctionApplication {
1061 fn_ref, arguments, ..
1062 } => {
1063 let fn_decl_id = ctx.get_normalized_fn_node_id(fn_ref.id());
1064
1065 let fn_node = ctx.get_node_for_fn_decl(&fn_decl_id);
1066 if let Some(fn_node) = fn_node {
1067 ctx.add_edge_from_current(
1068 fn_node,
1069 TyNodeDepGraphEdge(TyNodeDepGraphEdgeInfo::FnApp),
1070 );
1071
1072 if !ctx.node_stack.contains(&fn_node) {
1073 let _ = fn_decl_id.type_check_analyze(handler, ctx);
1074 }
1075 }
1076
1077 let decl = ctx.engines.de().get(fn_ref.id());
1079
1080 use crate::type_system::unify::unifier::*;
1081 let unifier = Unifier::new(ctx.engines, "", UnifyKind::Default);
1082
1083 for (decl_param, arg) in decl.parameters.iter().zip(arguments.iter()) {
1084 unifier.unify(
1085 handler,
1086 arg.1.return_type,
1087 decl_param.type_argument.type_id(),
1088 &Span::dummy(),
1089 false,
1090 );
1091 }
1092 }
1093 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
1094 lhs.type_check_analyze(handler, ctx)?;
1095 rhs.type_check_analyze(handler, ctx)?
1096 }
1097 TyExpressionVariant::ConstantExpression { decl, .. } => {
1098 decl.type_check_analyze(handler, ctx)?
1099 }
1100 TyExpressionVariant::ConfigurableExpression { decl, .. } => {
1101 decl.type_check_analyze(handler, ctx)?
1102 }
1103 TyExpressionVariant::ConstGenericExpression { decl, .. } => {
1104 decl.type_check_analyze(handler, ctx)?
1105 }
1106 TyExpressionVariant::VariableExpression { .. } => {}
1107 TyExpressionVariant::Tuple { fields } => {
1108 for field in fields.iter() {
1109 field.type_check_analyze(handler, ctx)?
1110 }
1111 }
1112 TyExpressionVariant::ArrayExplicit { contents, .. } => {
1113 for elem in contents.iter() {
1114 elem.type_check_analyze(handler, ctx)?
1115 }
1116 }
1117 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
1118 value.type_check_analyze(handler, ctx)?;
1119 length.type_check_analyze(handler, ctx)?;
1120 }
1121 TyExpressionVariant::ArrayIndex { prefix, index } => {
1122 prefix.type_check_analyze(handler, ctx)?;
1123 index.type_check_analyze(handler, ctx)?;
1124 }
1125 TyExpressionVariant::StructExpression { fields: _, .. } => {}
1126 TyExpressionVariant::CodeBlock(block) => {
1127 block.type_check_analyze(handler, ctx)?;
1128 }
1129 TyExpressionVariant::FunctionParameter => {}
1130 TyExpressionVariant::MatchExp {
1131 desugared,
1132 scrutinees: _,
1133 } => {
1134 desugared.type_check_analyze(handler, ctx)?;
1135 }
1136 TyExpressionVariant::IfExp {
1137 condition,
1138 then,
1139 r#else,
1140 } => {
1141 condition.type_check_analyze(handler, ctx)?;
1142 then.type_check_analyze(handler, ctx)?;
1143 if let Some(r#else) = r#else {
1144 r#else.type_check_analyze(handler, ctx)?;
1145 }
1146 }
1147 TyExpressionVariant::AsmExpression { .. } => {}
1148 TyExpressionVariant::StructFieldAccess { prefix, .. } => {
1149 prefix.type_check_analyze(handler, ctx)?;
1150 }
1151 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
1152 prefix.type_check_analyze(handler, ctx)?;
1153 }
1154 TyExpressionVariant::EnumInstantiation { contents, .. } => {
1155 for expr in contents.iter() {
1156 expr.type_check_analyze(handler, ctx)?
1157 }
1158 }
1159 TyExpressionVariant::AbiCast { address, .. } => {
1160 address.type_check_analyze(handler, ctx)?;
1161 }
1162 TyExpressionVariant::StorageAccess(_node) => {}
1163 TyExpressionVariant::IntrinsicFunction(node) => {
1164 for arg in node.arguments.iter() {
1165 arg.type_check_analyze(handler, ctx)?
1166 }
1167 }
1168 TyExpressionVariant::AbiName(_node) => {}
1169 TyExpressionVariant::EnumTag { exp } => {
1170 exp.type_check_analyze(handler, ctx)?;
1171 }
1172 TyExpressionVariant::UnsafeDowncast { exp, .. } => {
1173 exp.type_check_analyze(handler, ctx)?;
1174 }
1175 TyExpressionVariant::WhileLoop { condition, body } => {
1176 condition.type_check_analyze(handler, ctx)?;
1177 body.type_check_analyze(handler, ctx)?;
1178 }
1179 TyExpressionVariant::ForLoop { desugared } => {
1180 desugared.type_check_analyze(handler, ctx)?;
1181 }
1182 TyExpressionVariant::Break => {}
1183 TyExpressionVariant::Continue => {}
1184 TyExpressionVariant::Reassignment(node) => {
1185 node.type_check_analyze(handler, ctx)?;
1186 }
1187 TyExpressionVariant::ImplicitReturn(exp) | TyExpressionVariant::Return(exp) => {
1188 exp.type_check_analyze(handler, ctx)?;
1189 }
1190 TyExpressionVariant::Panic(exp) => {
1191 exp.type_check_analyze(handler, ctx)?;
1192 }
1193 TyExpressionVariant::Ref(exp) | TyExpressionVariant::Deref(exp) => {
1194 exp.type_check_analyze(handler, ctx)?;
1195 }
1196 }
1197 Ok(())
1198 }
1199}
1200
1201impl TypeCheckFinalization for TyExpressionVariant {
1202 fn type_check_finalize(
1203 &mut self,
1204 handler: &Handler,
1205 ctx: &mut TypeCheckFinalizationContext,
1206 ) -> Result<(), ErrorEmitted> {
1207 handler.scope(|handler| {
1208 match self {
1209 TyExpressionVariant::ConstGenericExpression { .. } => {}
1210 TyExpressionVariant::Literal(_) => {}
1211 TyExpressionVariant::FunctionApplication { arguments, .. } => {
1212 for (_, arg) in arguments.iter_mut() {
1213 let _ = arg.type_check_finalize(handler, ctx);
1214 }
1215 }
1216 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
1217 lhs.type_check_finalize(handler, ctx)?;
1218 rhs.type_check_finalize(handler, ctx)?
1219 }
1220 TyExpressionVariant::ConstantExpression { decl, .. } => {
1221 decl.type_check_finalize(handler, ctx)?
1222 }
1223 TyExpressionVariant::ConfigurableExpression { decl, .. } => {
1224 decl.type_check_finalize(handler, ctx)?
1225 }
1226 TyExpressionVariant::VariableExpression { .. } => {}
1227 TyExpressionVariant::Tuple { fields } => {
1228 for field in fields.iter_mut() {
1229 field.type_check_finalize(handler, ctx)?
1230 }
1231 }
1232 TyExpressionVariant::ArrayExplicit { contents, .. } => {
1233 for elem in contents.iter_mut() {
1234 elem.type_check_finalize(handler, ctx)?
1235 }
1236 }
1237 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
1238 value.type_check_finalize(handler, ctx)?;
1239 length.type_check_finalize(handler, ctx)?;
1240 }
1241 TyExpressionVariant::ArrayIndex { prefix, index } => {
1242 prefix.type_check_finalize(handler, ctx)?;
1243 index.type_check_finalize(handler, ctx)?;
1244 }
1245 TyExpressionVariant::StructExpression { fields, .. } => {
1246 for field in fields.iter_mut() {
1247 field.type_check_finalize(handler, ctx)?;
1248 }
1249 }
1250 TyExpressionVariant::CodeBlock(block) => {
1251 block.type_check_finalize(handler, ctx)?;
1252 }
1253 TyExpressionVariant::FunctionParameter => {}
1254 TyExpressionVariant::MatchExp {
1255 desugared,
1256 scrutinees,
1257 } => {
1258 desugared.type_check_finalize(handler, ctx)?;
1259 for scrutinee in scrutinees.iter_mut() {
1260 scrutinee.type_check_finalize(handler, ctx)?
1261 }
1262 }
1263 TyExpressionVariant::IfExp {
1264 condition,
1265 then,
1266 r#else,
1267 } => {
1268 condition.type_check_finalize(handler, ctx)?;
1269 then.type_check_finalize(handler, ctx)?;
1270 if let Some(ref mut r#else) = r#else {
1271 r#else.type_check_finalize(handler, ctx)?;
1272 }
1273 }
1274 TyExpressionVariant::AsmExpression { .. } => {}
1275 TyExpressionVariant::StructFieldAccess { prefix, .. } => {
1276 prefix.type_check_finalize(handler, ctx)?;
1277 }
1278 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
1279 prefix.type_check_finalize(handler, ctx)?;
1280 }
1281 TyExpressionVariant::EnumInstantiation { contents, .. } => {
1282 for expr in contents.iter_mut() {
1283 expr.type_check_finalize(handler, ctx)?
1284 }
1285 }
1286 TyExpressionVariant::AbiCast { address, .. } => {
1287 address.type_check_finalize(handler, ctx)?;
1288 }
1289 TyExpressionVariant::StorageAccess(_) => {
1290 todo!("")
1291 }
1292 TyExpressionVariant::IntrinsicFunction(kind) => {
1293 for expr in kind.arguments.iter_mut() {
1294 expr.type_check_finalize(handler, ctx)?;
1295 }
1296 }
1297 TyExpressionVariant::AbiName(_) => {
1298 todo!("")
1299 }
1300 TyExpressionVariant::EnumTag { exp } => {
1301 exp.type_check_finalize(handler, ctx)?;
1302 }
1303 TyExpressionVariant::UnsafeDowncast { exp, .. } => {
1304 exp.type_check_finalize(handler, ctx)?;
1305 }
1306 TyExpressionVariant::WhileLoop { condition, body } => {
1307 condition.type_check_finalize(handler, ctx)?;
1308 body.type_check_finalize(handler, ctx)?;
1309 }
1310 TyExpressionVariant::ForLoop { desugared } => {
1311 desugared.type_check_finalize(handler, ctx)?;
1312 }
1313 TyExpressionVariant::Break => {}
1314 TyExpressionVariant::Continue => {}
1315 TyExpressionVariant::Reassignment(node) => {
1316 node.type_check_finalize(handler, ctx)?;
1317 }
1318 TyExpressionVariant::ImplicitReturn(exp) | TyExpressionVariant::Return(exp) => {
1319 exp.type_check_finalize(handler, ctx)?;
1320 }
1321 TyExpressionVariant::Panic(exp) => {
1322 exp.type_check_finalize(handler, ctx)?;
1323 }
1324 TyExpressionVariant::Ref(exp) | TyExpressionVariant::Deref(exp) => {
1325 exp.type_check_finalize(handler, ctx)?;
1326 }
1327 }
1328 Ok(())
1329 })
1330 }
1331}
1332
1333impl UpdateConstantExpression for TyExpressionVariant {
1334 fn update_constant_expression(&mut self, engines: &Engines, implementing_type: &TyDecl) {
1335 use TyExpressionVariant::*;
1336 match self {
1337 Literal(..) => (),
1338 FunctionApplication { .. } => (),
1339 LazyOperator { lhs, rhs, .. } => {
1340 (*lhs).update_constant_expression(engines, implementing_type);
1341 (*rhs).update_constant_expression(engines, implementing_type);
1342 }
1343 ConstantExpression { ref mut decl, .. } => {
1344 if let Some(impl_const) =
1345 find_const_decl_from_impl(implementing_type, engines.de(), decl)
1346 {
1347 *decl = Box::new(impl_const);
1348 }
1349 }
1350 ConfigurableExpression { .. } => {
1351 unreachable!()
1352 }
1353 ConstGenericExpression { .. } => {}
1354 VariableExpression { .. } => (),
1355 Tuple { fields } => fields
1356 .iter_mut()
1357 .for_each(|x| x.update_constant_expression(engines, implementing_type)),
1358 ArrayExplicit {
1359 contents,
1360 elem_type: _,
1361 } => contents
1362 .iter_mut()
1363 .for_each(|x| x.update_constant_expression(engines, implementing_type)),
1364 ArrayRepeat {
1365 elem_type: _,
1366 value,
1367 length,
1368 } => {
1369 value.update_constant_expression(engines, implementing_type);
1370 length.update_constant_expression(engines, implementing_type);
1371 }
1372 ArrayIndex { prefix, index } => {
1373 (*prefix).update_constant_expression(engines, implementing_type);
1374 (*index).update_constant_expression(engines, implementing_type);
1375 }
1376 StructExpression { fields, .. } => fields.iter_mut().for_each(|x| {
1377 x.value
1378 .update_constant_expression(engines, implementing_type)
1379 }),
1380 CodeBlock(block) => {
1381 block.update_constant_expression(engines, implementing_type);
1382 }
1383 FunctionParameter => (),
1384 MatchExp { desugared, .. } => {
1385 desugared.update_constant_expression(engines, implementing_type)
1386 }
1387 IfExp {
1388 condition,
1389 then,
1390 r#else,
1391 } => {
1392 condition.update_constant_expression(engines, implementing_type);
1393 then.update_constant_expression(engines, implementing_type);
1394 if let Some(ref mut r#else) = r#else {
1395 r#else.update_constant_expression(engines, implementing_type);
1396 }
1397 }
1398 AsmExpression { .. } => {}
1399 StructFieldAccess { prefix, .. } => {
1400 prefix.update_constant_expression(engines, implementing_type);
1401 }
1402 TupleElemAccess { prefix, .. } => {
1403 prefix.update_constant_expression(engines, implementing_type);
1404 }
1405 EnumInstantiation {
1406 enum_ref: _,
1407 contents,
1408 ..
1409 } => {
1410 if let Some(ref mut contents) = contents {
1411 contents.update_constant_expression(engines, implementing_type);
1412 };
1413 }
1414 AbiCast { address, .. } => {
1415 address.update_constant_expression(engines, implementing_type)
1416 }
1417 StorageAccess { .. } => (),
1418 IntrinsicFunction(_) => {}
1419 EnumTag { exp } => {
1420 exp.update_constant_expression(engines, implementing_type);
1421 }
1422 UnsafeDowncast { exp, .. } => {
1423 exp.update_constant_expression(engines, implementing_type);
1424 }
1425 AbiName(_) => (),
1426 WhileLoop {
1427 ref mut condition,
1428 ref mut body,
1429 } => {
1430 condition.update_constant_expression(engines, implementing_type);
1431 body.update_constant_expression(engines, implementing_type);
1432 }
1433 ForLoop { ref mut desugared } => {
1434 desugared.update_constant_expression(engines, implementing_type);
1435 }
1436 Break => (),
1437 Continue => (),
1438 Reassignment(reassignment) => {
1439 reassignment.update_constant_expression(engines, implementing_type)
1440 }
1441 ImplicitReturn(exp) | Return(exp) => {
1442 exp.update_constant_expression(engines, implementing_type)
1443 }
1444 Panic(exp) => exp.update_constant_expression(engines, implementing_type),
1445 Ref(exp) | Deref(exp) => exp.update_constant_expression(engines, implementing_type),
1446 }
1447 }
1448}
1449
1450fn find_const_decl_from_impl(
1451 implementing_type: &TyDecl,
1452 decl_engine: &DeclEngine,
1453 const_decl: &TyConstantDecl,
1454) -> Option<TyConstantDecl> {
1455 match implementing_type {
1456 TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id, .. }) => {
1457 let impl_trait = decl_engine.get_impl_self_or_trait(&decl_id.clone());
1458 impl_trait
1459 .items
1460 .iter()
1461 .find(|item| match item {
1462 TyTraitItem::Constant(decl_id) => {
1463 let trait_const_decl =
1464 (*decl_engine.get_constant(&decl_id.clone())).clone();
1465 const_decl.name().eq(trait_const_decl.name())
1466 }
1467 _ => false,
1468 })
1469 .map(|item| match item {
1470 TyTraitItem::Constant(decl_id) => (*decl_engine.get_constant(decl_id)).clone(),
1471 _ => unreachable!(),
1472 })
1473 }
1474 TyDecl::AbiDecl(AbiDecl {
1475 decl_id: _decl_id, ..
1476 }) => todo!(""),
1477 _ => unreachable!(),
1478 }
1479}
1480
1481impl DisplayWithEngines for TyExpressionVariant {
1482 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
1483 DebugWithEngines::fmt(self, f, engines)
1485 }
1486}
1487
1488impl DebugWithEngines for TyExpressionVariant {
1489 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
1490 let s = match self {
1491 TyExpressionVariant::ConstGenericExpression { .. } => {
1492 todo!("Will be implemented by https://github.com/FuelLabs/sway/issues/6860")
1493 }
1494 TyExpressionVariant::Literal(lit) => format!("literal {lit}"),
1495 TyExpressionVariant::FunctionApplication {
1496 call_path: name, ..
1497 } => {
1498 format!("\"{}\" fn entry", name.suffix.as_str())
1499 }
1500 TyExpressionVariant::LazyOperator { op, .. } => match op {
1501 LazyOp::And => "&&".into(),
1502 LazyOp::Or => "||".into(),
1503 },
1504 TyExpressionVariant::Tuple { fields } => {
1505 let fields = fields
1506 .iter()
1507 .map(|field| format!("{:?}", engines.help_out(field)))
1508 .collect::<Vec<_>>()
1509 .join(", ");
1510 format!("tuple({fields})")
1511 }
1512 TyExpressionVariant::ArrayExplicit { .. } | TyExpressionVariant::ArrayRepeat { .. } => {
1513 "array".into()
1514 }
1515 TyExpressionVariant::ArrayIndex { .. } => "[..]".into(),
1516 TyExpressionVariant::StructExpression { struct_id, .. } => {
1517 let decl = engines.de().get(struct_id);
1518 format!("\"{}\" struct init", decl.name().as_str())
1519 }
1520 TyExpressionVariant::CodeBlock(_) => "code block entry".into(),
1521 TyExpressionVariant::FunctionParameter => "fn param access".into(),
1522 TyExpressionVariant::MatchExp { .. } | TyExpressionVariant::IfExp { .. } => {
1523 "if exp".into()
1524 }
1525 TyExpressionVariant::AsmExpression { .. } => "inline asm".into(),
1526 TyExpressionVariant::AbiCast { abi_name, .. } => {
1527 format!("abi cast {}", abi_name.suffix.as_str())
1528 }
1529 TyExpressionVariant::StructFieldAccess {
1530 resolved_type_of_parent,
1531 field_to_access,
1532 ..
1533 } => {
1534 format!(
1535 "\"{:?}.{}\" struct field access",
1536 engines.help_out(*resolved_type_of_parent),
1537 field_to_access.name
1538 )
1539 }
1540 TyExpressionVariant::TupleElemAccess {
1541 resolved_type_of_parent,
1542 elem_to_access_num,
1543 ..
1544 } => {
1545 format!(
1546 "\"{:?}.{}\" tuple index",
1547 engines.help_out(*resolved_type_of_parent),
1548 elem_to_access_num
1549 )
1550 }
1551 TyExpressionVariant::ConstantExpression { decl, .. } => {
1552 format!("\"{}\" constant exp", decl.name().as_str())
1553 }
1554 TyExpressionVariant::ConfigurableExpression { decl, .. } => {
1555 format!("\"{}\" configurable exp", decl.name().as_str())
1556 }
1557 TyExpressionVariant::VariableExpression { name, .. } => {
1558 format!("\"{}\" variable exp", name.as_str())
1559 }
1560 TyExpressionVariant::EnumInstantiation {
1561 tag,
1562 enum_ref,
1563 variant_name,
1564 ..
1565 } => {
1566 format!(
1567 "{}::{} enum instantiation (tag: {})",
1568 enum_ref.name().as_str(),
1569 variant_name.as_str(),
1570 tag
1571 )
1572 }
1573 TyExpressionVariant::StorageAccess(access) => {
1574 format!("storage field {} access", access.storage_field_name())
1575 }
1576 TyExpressionVariant::IntrinsicFunction(kind) => format!("{:?}", engines.help_out(kind)),
1577 TyExpressionVariant::AbiName(n) => format!("ABI name {n}"),
1578 TyExpressionVariant::EnumTag { exp } => {
1579 format!("({:?} as tag)", engines.help_out(exp.return_type))
1580 }
1581 TyExpressionVariant::UnsafeDowncast {
1582 exp,
1583 variant,
1584 call_path_decl,
1585 } => {
1586 format!(
1587 "({:?} as {}::{})",
1588 engines.help_out(exp.return_type),
1589 engines.help_out(call_path_decl),
1590 variant.name
1591 )
1592 }
1593 TyExpressionVariant::WhileLoop { condition, .. } => {
1594 format!("while loop on {:?}", engines.help_out(&**condition))
1595 }
1596 TyExpressionVariant::ForLoop { .. } => "for loop".to_string(),
1597 TyExpressionVariant::Break => "break".to_string(),
1598 TyExpressionVariant::Continue => "continue".to_string(),
1599 TyExpressionVariant::Reassignment(reassignment) => {
1600 let target = match &reassignment.lhs {
1601 TyReassignmentTarget::DerefAccess { exp, indices } => {
1602 let mut target = format!("{:?}", engines.help_out(exp));
1603 for index in indices {
1604 match index {
1605 ProjectionKind::StructField {
1606 name,
1607 field_to_access: _,
1608 } => {
1609 target.push('.');
1610 target.push_str(name.as_str());
1611 }
1612 ProjectionKind::TupleField { index, .. } => {
1613 target.push('.');
1614 target.push_str(index.to_string().as_str());
1615 }
1616 ProjectionKind::ArrayIndex { index, .. } => {
1617 write!(&mut target, "[{:?}]", engines.help_out(index)).unwrap();
1618 }
1619 }
1620 }
1621 target
1622 }
1623 TyReassignmentTarget::ElementAccess {
1624 base_name,
1625 base_type: _,
1626 indices,
1627 } => {
1628 let mut target = base_name.to_string();
1629 for index in indices {
1630 match index {
1631 ProjectionKind::StructField {
1632 name,
1633 field_to_access: _,
1634 } => {
1635 target.push('.');
1636 target.push_str(name.as_str());
1637 }
1638 ProjectionKind::TupleField { index, .. } => {
1639 target.push('.');
1640 target.push_str(index.to_string().as_str());
1641 }
1642 ProjectionKind::ArrayIndex { index, .. } => {
1643 write!(&mut target, "[{:?}]", engines.help_out(index)).unwrap();
1644 }
1645 }
1646 }
1647 target
1648 }
1649 };
1650
1651 format!(
1652 "reassignment to {target} = {:?}",
1653 engines.help_out(&reassignment.rhs)
1654 )
1655 }
1656 TyExpressionVariant::ImplicitReturn(exp) => {
1657 format!("implicit return {:?}", engines.help_out(&**exp))
1658 }
1659 TyExpressionVariant::Return(exp) => {
1660 format!("return {:?}", engines.help_out(&**exp))
1661 }
1662 TyExpressionVariant::Panic(exp) => {
1663 format!("panic {:?}", engines.help_out(&**exp))
1664 }
1665 TyExpressionVariant::Ref(exp) => {
1666 format!("&({:?})", engines.help_out(&**exp))
1667 }
1668 TyExpressionVariant::Deref(exp) => {
1669 format!("*({:?})", engines.help_out(&**exp))
1670 }
1671 };
1672 write!(f, "{s}")
1673 }
1674}
1675
1676impl TyExpressionVariant {
1677 pub(crate) fn extract_literal_value(&self) -> Option<Literal> {
1679 match self {
1680 TyExpressionVariant::Literal(value) => Some(value.clone()),
1681 _ => None,
1682 }
1683 }
1684}