Skip to main content

sway_core/language/ty/expression/
expression_variant.rs

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        /// Optional binding information for the LSP.
35        type_binding: Option<TypeBinding<()>>,
36        /// In case of a method call, a [TypeId] of the method target (self).
37        /// E.g., `method_target.some_method()`.
38        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    // a flag that this value will later be provided as a parameter, but is currently unknown
92    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    // like a variable expression but it has multiple parts,
109    // like looking up a field in a struct
110    StructFieldAccess {
111        prefix: Box<TyExpression>,
112        field_to_access: TyStructField,
113        field_instantiation_span: Span,
114        /// Final resolved type of the `prefix` part
115        /// of the expression. This will always be
116        /// a [TypeId] of a struct, never an alias
117        /// or a reference to a struct.
118        /// The original parent might be an alias
119        /// or a direct or indirect reference to a
120        /// struct.
121        resolved_type_of_parent: TypeId,
122    },
123    TupleElemAccess {
124        prefix: Box<TyExpression>,
125        elem_to_access_num: usize,
126        /// Final resolved type of the `prefix` part
127        /// of the expression. This will always be
128        /// a [TypeId] of a tuple, never an alias
129        /// or a reference to a tuple.
130        /// The original parent might be an alias
131        /// or a direct or indirect reference to a
132        /// tuple.
133        resolved_type_of_parent: TypeId,
134        elem_to_access_span: Span,
135    },
136    EnumInstantiation {
137        enum_ref: DeclRef<DeclId<TyEnumDecl>>,
138        /// for printing
139        variant_name: Ident,
140        tag: usize,
141        contents: Option<Box<TyExpression>>,
142        /// If there is an error regarding this instantiation of the enum,
143        /// use these spans as it points to the call site and not the declaration.
144        /// They are also used in the language server.
145        variant_instantiation_span: Span,
146        call_path_binding: TypeBinding<CallPath>,
147        /// The enum type, can be a type alias.
148        call_path_decl: ty::TyDecl,
149    },
150    AbiCast {
151        abi_name: CallPath,
152        address: Box<TyExpression>,
153        #[allow(dead_code)]
154        // this span may be used for errors in the future, although it is not right now.
155        span: Span,
156    },
157    StorageAccess(TyStorageAccess),
158    IntrinsicFunction(TyIntrinsicFunctionKind),
159    /// a zero-sized type-system-only compile-time thing that is used for constructing ABI casts.
160    AbiName(AbiName),
161    /// grabs the enum tag from the particular enum and variant of the `exp`
162    EnumTag {
163        exp: Box<TyExpression>,
164    },
165    /// performs an unsafe cast from the `exp` to the type of the given enum `variant`
166    UnsafeDowncast {
167        exp: Box<TyExpression>,
168        variant: TyEnumVariant,
169        /// Should contain a TyDecl to either an enum or a type alias.
170        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                // these fields are not hashed because they aren't relevant/a
466                // reliable source of obj v. obj distinction
467                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                // these fields are not hashed because they aren't relevant/a
510                // reliable source of obj v. obj distinction
511                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                // these fields are not hashed because they aren't relevant/a
542                // reliable source of obj v. obj distinction
543                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                // these fields are not hashed because they aren't relevant/a
555                // reliable source of obj v. obj distinction
556                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                // these fields are not hashed because they aren't relevant/a
576                // reliable source of obj v. obj distinction
577                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                // these fields are not hashed because they aren't relevant/a
588                // reliable source of obj v. obj distinction
589                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                // these fields are not hashed because they aren't relevant/a
602                // reliable source of obj v. obj distinction
603                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                // these fields are not hashed because they aren't relevant/a
617                // reliable source of obj v. obj distinction
618                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                // these fields are not hashed because they aren't relevant/a
633                // reliable source of obj v. obj distinction
634                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, //: Vec<TyAsmRegisterDeclaration>,
765                ..
766            } => registers.subst(ctx),
767            // like a variable expression but it has multiple parts,
768            // like looking up a field in a struct
769            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            // storage is never generic and cannot be monomorphized
803            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                    // Finds method implementation for method dummy and replaces it.
864                    // This is required because dummy methods don't have type parameters from impl traits.
865                    // Thus we use the implemented method that already contains all the required type parameters,
866                    // including those from the impl trait.
867                    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                            // find method and improve error
875                            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                    // Handle the trait constraints. This includes checking to see if the trait
920                    // constraints are satisfied and replacing old decl ids based on the
921                    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                    // TODO: replace enum decl
1041                    //enum_decl.replace_decls(decl_mapping);
1042                    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                // Unify arguments that are still not concrete
1119                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        // TODO: Implement user-friendly display strings if needed.
1531        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    /// Returns `self` as a literal, if possible.
1725    pub(crate) fn extract_literal_value(&self) -> Option<Literal> {
1726        match self {
1727            TyExpressionVariant::Literal(value) => Some(value.clone()),
1728            _ => None,
1729        }
1730    }
1731}