Skip to main content

sway_core/language/ty/expression/
expression_variant.rs

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