sway_core/language/ty/declaration/
struct.rs1use crate::{
2 decl_engine::MaterializeConstGenerics,
3 engine_threading::*,
4 error::module_can_be_changed,
5 has_changes,
6 language::{
7 parsed::StructDeclaration, ty::TyDeclParsedType, CallPath, CallPathType, Visibility,
8 },
9 transform,
10 type_system::*,
11 Namespace,
12};
13use monomorphization::MonomorphizeHelper;
14use serde::{Deserialize, Serialize};
15use std::{
16 cmp::Ordering,
17 hash::{Hash, Hasher},
18};
19use sway_error::handler::{ErrorEmitted, Handler};
20use sway_types::{Ident, Named, Span, Spanned};
21
22#[derive(Clone, Debug, Serialize, Deserialize)]
23pub struct TyStructDecl {
24 pub call_path: CallPath,
25 pub fields: Vec<TyStructField>,
26 pub type_parameters: Vec<TypeParameter>,
27 pub visibility: Visibility,
28 pub span: Span,
29 pub attributes: transform::Attributes,
30}
31
32impl TyDeclParsedType for TyStructDecl {
33 type ParsedType = StructDeclaration;
34}
35
36impl Named for TyStructDecl {
37 fn name(&self) -> &Ident {
38 &self.call_path.suffix
39 }
40}
41
42impl EqWithEngines for TyStructDecl {}
43impl PartialEqWithEngines for TyStructDecl {
44 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
45 self.call_path == other.call_path
46 && self.fields.eq(&other.fields, ctx)
47 && self.type_parameters.eq(&other.type_parameters, ctx)
48 && self.visibility == other.visibility
49 }
50}
51
52impl HashWithEngines for TyStructDecl {
53 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
54 let TyStructDecl {
55 call_path,
56 fields,
57 type_parameters,
58 visibility,
59 span: _,
62 attributes: _,
63 } = self;
64 call_path.hash(state);
65 fields.hash(state, engines);
66 type_parameters.hash(state, engines);
67 visibility.hash(state);
68 }
69}
70
71impl SubstTypes for TyStructDecl {
72 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
73 has_changes! {
74 self.fields.subst(ctx);
75 self.type_parameters.subst(ctx);
76 }
77 }
78}
79
80impl Spanned for TyStructDecl {
81 fn span(&self) -> Span {
82 self.span.clone()
83 }
84}
85
86impl MonomorphizeHelper for TyStructDecl {
87 fn type_parameters(&self) -> &[TypeParameter] {
88 &self.type_parameters
89 }
90
91 fn name(&self) -> &Ident {
92 &self.call_path.suffix
93 }
94
95 fn has_self_type_param(&self) -> bool {
96 false
97 }
98}
99
100impl MaterializeConstGenerics for TyStructDecl {
101 fn materialize_const_generics(
102 &mut self,
103 _engines: &Engines,
104 _handler: &Handler,
105 _name: &str,
106 _value: &crate::language::ty::TyExpression,
107 ) -> Result<(), ErrorEmitted> {
108 Ok(())
109 }
110}
111
112impl TyStructDecl {
113 pub(crate) fn accessible_fields_names(&self, is_public_struct_access: bool) -> Vec<Ident> {
118 TyStructField::accessible_fields_names(&self.fields, is_public_struct_access)
119 }
120
121 pub(crate) fn find_field(&self, field_name: &Ident) -> Option<&TyStructField> {
124 self.fields.iter().find(|field| field.name == *field_name)
125 }
126
127 pub(crate) fn get_field_index_and_type(&self, field_name: &Ident) -> Option<(u64, TypeId)> {
131 self.fields
135 .iter()
136 .enumerate()
137 .find(|(_, field)| field.name == *field_name)
138 .map(|(idx, field)| (idx as u64, field.type_argument.type_id()))
139 }
140
141 pub(crate) fn has_private_fields(&self) -> bool {
143 self.fields.iter().any(|field| field.is_private())
144 }
145
146 pub(crate) fn has_only_private_fields(&self) -> bool {
149 !self.is_empty() && self.fields.iter().all(|field| field.is_private())
150 }
151
152 pub(crate) fn is_empty(&self) -> bool {
154 self.fields.is_empty()
155 }
156}
157
158pub struct StructAccessInfo {
160 struct_can_be_changed: bool,
163 is_public_struct_access: bool,
166}
167
168impl StructAccessInfo {
169 pub fn get_info(engines: &Engines, struct_decl: &TyStructDecl, namespace: &Namespace) -> Self {
170 assert!(
171 matches!(struct_decl.call_path.callpath_type, CallPathType::Full),
172 "The call path of the struct declaration must always be fully resolved."
173 );
174
175 let struct_can_be_changed =
176 module_can_be_changed(engines, namespace, &struct_decl.call_path.prefixes);
177 let is_public_struct_access =
178 !namespace.module_is_submodule_of(&struct_decl.call_path.prefixes, true);
179
180 Self {
181 struct_can_be_changed,
182 is_public_struct_access,
183 }
184 }
185}
186
187impl From<StructAccessInfo> for (bool, bool) {
188 fn from(struct_access_info: StructAccessInfo) -> (bool, bool) {
190 let StructAccessInfo {
191 struct_can_be_changed,
192 is_public_struct_access,
193 } = struct_access_info;
194 (struct_can_be_changed, is_public_struct_access)
195 }
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct TyStructField {
200 pub visibility: Visibility,
201 pub name: Ident,
202 pub span: Span,
203 pub type_argument: GenericArgument,
204 pub attributes: transform::Attributes,
205}
206
207impl TyStructField {
208 pub fn is_private(&self) -> bool {
209 matches!(self.visibility, Visibility::Private)
210 }
211
212 pub fn is_public(&self) -> bool {
213 matches!(self.visibility, Visibility::Public)
214 }
215
216 pub(crate) fn accessible_fields(
220 fields: &[TyStructField],
221 is_public_struct_access: bool,
222 ) -> impl Iterator<Item = &TyStructField> {
223 fields
224 .iter()
225 .filter(move |field| !is_public_struct_access || field.is_public())
226 }
227
228 pub(crate) fn accessible_fields_names(
233 fields: &[TyStructField],
234 is_public_struct_access: bool,
235 ) -> Vec<Ident> {
236 Self::accessible_fields(fields, is_public_struct_access)
237 .map(|field| field.name.clone())
238 .collect()
239 }
240}
241
242impl Spanned for TyStructField {
243 fn span(&self) -> Span {
244 self.span.clone()
245 }
246}
247
248impl HashWithEngines for TyStructField {
249 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
250 let TyStructField {
251 visibility,
252 name,
253 type_argument,
254 span: _,
257 attributes: _,
258 } = self;
259 visibility.hash(state);
260 name.hash(state);
261 type_argument.hash(state, engines);
262 }
263}
264
265impl EqWithEngines for TyStructField {}
266impl PartialEqWithEngines for TyStructField {
267 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
268 self.name == other.name && self.type_argument.eq(&other.type_argument, ctx)
269 }
270}
271
272impl OrdWithEngines for TyStructField {
273 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
274 let TyStructField {
275 name: ln,
276 type_argument: lta,
277 span: _,
279 attributes: _,
280 visibility: _,
281 } = self;
282 let TyStructField {
283 name: rn,
284 type_argument: rta,
285 span: _,
287 attributes: _,
288 visibility: _,
289 } = other;
290 ln.cmp(rn).then_with(|| lta.cmp(rta, ctx))
291 }
292}
293
294impl SubstTypes for TyStructField {
295 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
296 self.type_argument.subst_inner(ctx)
297 }
298}