use derivative::Derivative;
use sway_types::{Ident, Span};
use crate::{
error::{err, ok},
semantic_analysis::{
ast_node::{type_check_interface_surface, type_check_trait_methods},
TypeCheckContext,
},
type_system::{insert_type, AbiName, TypeId},
AbiDeclaration, CompileError, CompileResult, FunctionDeclaration, TypeInfo,
};
use super::{CreateTypeId, TypedTraitFn};
#[derive(Clone, Debug, Derivative)]
#[derivative(PartialEq, Eq)]
pub struct TypedAbiDeclaration {
pub name: Ident,
pub interface_surface: Vec<TypedTraitFn>,
#[derivative(PartialEq = "ignore")]
#[derivative(Eq(bound = ""))]
pub(crate) methods: Vec<FunctionDeclaration>,
#[derivative(PartialEq = "ignore")]
#[derivative(Eq(bound = ""))]
pub(crate) span: Span,
}
impl CreateTypeId for TypedAbiDeclaration {
fn create_type_id(&self) -> TypeId {
let ty = TypeInfo::ContractCaller {
abi_name: AbiName::Known(self.name.clone().into()),
address: None,
};
insert_type(ty)
}
}
impl TypedAbiDeclaration {
pub(crate) fn type_check(
ctx: TypeCheckContext,
abi_decl: AbiDeclaration,
) -> CompileResult<Self> {
let mut warnings = vec![];
let mut errors = vec![];
let AbiDeclaration {
name,
interface_surface,
methods,
span,
} = abi_decl;
let interface_surface = check!(
type_check_interface_surface(interface_surface, ctx.namespace),
return err(warnings, errors),
warnings,
errors
);
for typed_fn in &interface_surface {
for param in &typed_fn.parameters {
if param.is_reference && param.is_mutable {
errors.push(CompileError::RefMutableNotAllowedInContractAbi {
param_name: param.name.clone(),
})
}
}
}
let _methods = check!(
type_check_trait_methods(ctx, methods.clone()),
vec![],
warnings,
errors
);
for typed_fn in &methods {
for param in &typed_fn.parameters {
if param.is_reference && param.is_mutable {
errors.push(CompileError::RefMutableNotAllowedInContractAbi {
param_name: param.name.clone(),
})
}
}
}
let abi_decl = TypedAbiDeclaration {
interface_surface,
methods,
name,
span,
};
ok(abi_decl, warnings, errors)
}
}