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, Spanned};
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
79        for type_arg in self.type_arguments.iter() {
80            ctx.call_site_insert(type_arg.type_id(), type_arg.span());
81            types_metadata.append(&mut type_arg.type_id().collect_types_metadata(handler, ctx)?);
82        }
83        for arg in self.arguments.iter() {
84            types_metadata.append(&mut arg.collect_types_metadata(handler, ctx)?);
85        }
86
87        match self.kind {
88            Intrinsic::Log => {
89                let logged_type_id = TypeMetadata::get_logged_type_id(
90                    &self.arguments[0],
91                    ctx.experimental.new_encoding,
92                )
93                .map_err(|err| handler.emit_err(err))?;
94                let logged_type = TypeMetadata::new_logged_type(
95                    handler,
96                    ctx.engines,
97                    logged_type_id,
98                    ctx.program_name.clone(),
99                )?;
100                types_metadata.push(logged_type);
101            }
102            Intrinsic::Smo => {
103                types_metadata.push(TypeMetadata::MessageType(
104                    MessageId::new(ctx.message_id_counter()),
105                    self.arguments[1].return_type,
106                ));
107                *ctx.message_id_counter_mut() += 1;
108            }
109            _ => {}
110        }
111
112        Ok(types_metadata)
113    }
114}