sway_core/language/ty/declaration/
abi.rs1use super::{TyDeclParsedType, TyTraitInterfaceItem, TyTraitItem};
2use crate::{
3 ast_elements::type_parameter::ConstGenericExpr,
4 decl_engine::DeclEngineGet as _,
5 engine_threading::*,
6 language::parsed::{self, AbiDeclaration},
7 transform,
8 type_system::*,
9};
10use serde::{Deserialize, Serialize};
11use std::hash::{Hash, Hasher};
12use sway_error::{
13 error::CompileError,
14 handler::{ErrorEmitted, Handler},
15};
16use sway_types::{Ident, Named, Span, Spanned};
17
18#[derive(Clone, Debug, Serialize, Deserialize)]
21pub struct TyAbiDecl {
22 pub name: Ident,
24 pub interface_surface: Vec<TyTraitInterfaceItem>,
26 pub supertraits: Vec<parsed::Supertrait>,
27 pub items: Vec<TyTraitItem>,
28 pub span: Span,
29 pub attributes: transform::Attributes,
30}
31
32fn has_const_generics(type_id: TypeId, engines: &Engines) -> bool {
33 let types = type_id.extract_any_including_self(engines, &|_| true, vec![], 0);
34
35 for (t, _) in types {
36 let t = engines.te().get(t);
37 match &*t {
38 TypeInfo::StringArray(length) => match length.expr() {
39 ConstGenericExpr::Literal { .. } => {}
40 ConstGenericExpr::AmbiguousVariableExpression { .. } => return true,
41 },
42 TypeInfo::Enum(decl_id) => {
43 let decl = engines.de().get(decl_id);
44 let any_const_generics = decl
45 .generic_parameters
46 .iter()
47 .any(|x| x.as_const_parameter().is_some());
48 if any_const_generics {
49 return true;
50 }
51 }
52 TypeInfo::Struct(decl_id) => {
53 let decl = engines.de().get(decl_id);
54 let any_const_generics = decl
55 .generic_parameters
56 .iter()
57 .any(|x| x.as_const_parameter().is_some());
58 if any_const_generics {
59 return true;
60 }
61
62 for field in decl.fields.iter() {
63 let any_const_generics =
64 has_const_generics(field.type_argument.type_id, engines);
65 if any_const_generics {
66 return true;
67 }
68 }
69 }
70 TypeInfo::Tuple(items) => {
71 for item in items {
72 let any_const_generics = has_const_generics(item.type_id, engines);
73 if any_const_generics {
74 return true;
75 }
76 }
77 }
78 TypeInfo::Array(item, length) => {
79 let any_const_generics = has_const_generics(item.type_id, engines);
80 if any_const_generics {
81 return true;
82 }
83
84 match length.expr() {
85 ConstGenericExpr::Literal { .. } => {}
86 ConstGenericExpr::AmbiguousVariableExpression { .. } => return true,
87 }
88 }
89 _ => {}
90 }
91 }
92
93 false
94}
95
96impl TyAbiDecl {
97 pub(crate) fn forbid_const_generics(
98 &self,
99 handler: &Handler,
100 engines: &Engines,
101 ) -> Result<(), ErrorEmitted> {
102 for item in self.interface_surface.iter() {
103 match item {
104 TyTraitInterfaceItem::TraitFn(decl_ref) => {
105 let decl = engines.de().get(decl_ref.id());
106
107 if has_const_generics(decl.return_type.type_id, engines) {
108 let err = handler.emit_err(CompileError::ConstGenericNotSupportedHere {
109 span: decl.return_type.span(),
110 });
111 return Err(err);
112 }
113
114 for arg in decl.parameters.iter() {
115 if has_const_generics(arg.type_argument.type_id, engines) {
116 let err =
117 handler.emit_err(CompileError::ConstGenericNotSupportedHere {
118 span: arg.type_argument.span.clone(),
119 });
120 return Err(err);
121 }
122 }
123 }
124 TyTraitInterfaceItem::Constant(_) => {}
125 TyTraitInterfaceItem::Type(_) => {}
126 }
127 }
128
129 for item in self.items.iter() {
130 match item {
131 TyTraitItem::Fn(decl_ref) => {
132 let decl = engines.de().get(decl_ref.id());
133 if has_const_generics(decl.return_type.type_id, engines) {
134 let err = handler.emit_err(CompileError::ConstGenericNotSupportedHere {
135 span: decl.return_type.span(),
136 });
137 return Err(err);
138 }
139
140 for arg in decl.parameters.iter() {
141 if has_const_generics(arg.type_argument.type_id, engines) {
142 let err =
143 handler.emit_err(CompileError::ConstGenericNotSupportedHere {
144 span: arg.type_argument.span.clone(),
145 });
146 return Err(err);
147 }
148 }
149 }
150 TyTraitItem::Constant(_) => {}
151 TyTraitItem::Type(_) => {}
152 }
153 }
154
155 Ok(())
156 }
157}
158
159impl TyDeclParsedType for TyAbiDecl {
160 type ParsedType = AbiDeclaration;
161}
162
163impl EqWithEngines for TyAbiDecl {}
164impl PartialEqWithEngines for TyAbiDecl {
165 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
166 let TyAbiDecl {
167 name: ln,
168 interface_surface: lis,
169 supertraits: ls,
170 items: li,
171 attributes: _,
174 span: _,
175 } = self;
176 let TyAbiDecl {
177 name: rn,
178 interface_surface: ris,
179 supertraits: rs,
180 items: ri,
181 attributes: _,
184 span: _,
185 } = other;
186 ln == rn && lis.eq(ris, ctx) && li.eq(ri, ctx) && ls.eq(rs, ctx)
187 }
188}
189
190impl HashWithEngines for TyAbiDecl {
191 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
192 let TyAbiDecl {
193 name,
194 interface_surface,
195 items,
196 supertraits,
197 attributes: _,
200 span: _,
201 } = self;
202 name.hash(state);
203 interface_surface.hash(state, engines);
204 items.hash(state, engines);
205 supertraits.hash(state, engines);
206 }
207}
208
209impl CreateTypeId for TyAbiDecl {
210 fn create_type_id(&self, engines: &Engines) -> TypeId {
211 engines
212 .te()
213 .new_contract_caller(engines, AbiName::Known(self.name.clone().into()), None)
214 }
215}
216
217impl Spanned for TyAbiDecl {
218 fn span(&self) -> Span {
219 self.span.clone()
220 }
221}
222
223impl Named for TyAbiDecl {
224 fn name(&self) -> &Ident {
225 &self.name
226 }
227}