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