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