sway_core/language/ty/expression/
intrinsic_function.rs

1use crate::{engine_threading::*, has_changes, language::ty::*, type_system::*, types::*};
2use itertools::Itertools;
3use serde::{Deserialize, Serialize};
4use std::{
5    fmt,
6    hash::{Hash, Hasher},
7};
8use sway_ast::Intrinsic;
9use sway_error::handler::{ErrorEmitted, Handler};
10use sway_types::Span;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct TyIntrinsicFunctionKind {
14    pub kind: Intrinsic,
15    pub arguments: Vec<TyExpression>,
16    pub type_arguments: Vec<GenericArgument>,
17    pub span: Span,
18}
19
20impl EqWithEngines for TyIntrinsicFunctionKind {}
21impl PartialEqWithEngines for TyIntrinsicFunctionKind {
22    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
23        self.kind == other.kind
24            && self.arguments.eq(&other.arguments, ctx)
25            && self.type_arguments.eq(&other.type_arguments, ctx)
26    }
27}
28
29impl HashWithEngines for TyIntrinsicFunctionKind {
30    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
31        let TyIntrinsicFunctionKind {
32            kind,
33            arguments,
34            type_arguments,
35            // these fields are not hashed because they aren't relevant/a
36            // reliable source of obj v. obj distinction
37            span: _,
38        } = self;
39        kind.hash(state);
40        arguments.hash(state, engines);
41        type_arguments.hash(state, engines);
42    }
43}
44
45impl SubstTypes for TyIntrinsicFunctionKind {
46    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
47        has_changes! {
48            self.arguments.subst(ctx);
49            self.type_arguments.subst(ctx);
50        }
51    }
52}
53
54impl DebugWithEngines for TyIntrinsicFunctionKind {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
56        let targs = self
57            .type_arguments
58            .iter()
59            .map(|targ| format!("{:?}", engines.help_out(targ.type_id())))
60            .join(", ");
61        let args = self
62            .arguments
63            .iter()
64            .map(|e| format!("{:?}", engines.help_out(e)))
65            .join(", ");
66
67        write!(f, "{}::<{}>::({})", self.kind, targs, args)
68    }
69}
70
71impl CollectTypesMetadata for TyIntrinsicFunctionKind {
72    fn collect_types_metadata(
73        &self,
74        handler: &Handler,
75        ctx: &mut CollectTypesMetadataContext,
76    ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
77        let mut types_metadata = vec![];
78        for type_arg in self.type_arguments.iter() {
79            types_metadata.append(&mut type_arg.type_id().collect_types_metadata(handler, ctx)?);
80        }
81        for arg in self.arguments.iter() {
82            types_metadata.append(&mut arg.collect_types_metadata(handler, ctx)?);
83        }
84
85        match self.kind {
86            Intrinsic::Log => {
87                let logged_type_id = TypeMetadata::get_logged_type_id(
88                    &self.arguments[0],
89                    ctx.experimental.new_encoding,
90                )
91                .map_err(|err| handler.emit_err(err))?;
92                let logged_type = TypeMetadata::new_logged_type(
93                    ctx.engines,
94                    logged_type_id,
95                    ctx.program_name.clone(),
96                );
97                types_metadata.push(logged_type);
98            }
99            Intrinsic::Smo => {
100                types_metadata.push(TypeMetadata::MessageType(
101                    MessageId::new(ctx.message_id_counter()),
102                    self.arguments[1].return_type,
103                ));
104                *ctx.message_id_counter_mut() += 1;
105            }
106            _ => {}
107        }
108
109        Ok(types_metadata)
110    }
111}