sway_core/language/ty/declaration/
trait.rs

1use crate::{
2    decl_engine::{
3        DeclEngineReplace, DeclRefConstant, DeclRefFunction, DeclRefTraitFn, DeclRefTraitType,
4        MaterializeConstGenerics, ReplaceFunctionImplementingType,
5    },
6    engine_threading::*,
7    has_changes,
8    language::{
9        parsed::{self, TraitDeclaration},
10        ty::{TyDecl, TyDeclParsedType},
11        CallPath, Visibility,
12    },
13    semantic_analysis::{
14        TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckFinalization,
15        TypeCheckFinalizationContext,
16    },
17    transform,
18    type_system::*,
19};
20use monomorphization::MonomorphizeHelper;
21use serde::{Deserialize, Serialize};
22use std::{
23    fmt,
24    hash::{Hash, Hasher},
25};
26use sway_error::handler::{ErrorEmitted, Handler};
27use sway_types::{Ident, Named, Span, Spanned};
28
29#[derive(Clone, Debug, Serialize, Deserialize)]
30pub struct TyTraitDecl {
31    pub name: Ident,
32    pub type_parameters: Vec<TypeParameter>,
33    pub self_type: TypeParameter,
34    pub interface_surface: Vec<TyTraitInterfaceItem>,
35    pub items: Vec<TyTraitItem>,
36    pub supertraits: Vec<parsed::Supertrait>,
37    pub visibility: Visibility,
38    pub attributes: transform::AttributesMap,
39    pub call_path: CallPath,
40    pub span: Span,
41}
42
43impl TyDeclParsedType for TyTraitDecl {
44    type ParsedType = TraitDeclaration;
45}
46
47#[derive(Clone, Debug, Serialize, Deserialize)]
48pub enum TyTraitInterfaceItem {
49    TraitFn(DeclRefTraitFn),
50    Constant(DeclRefConstant),
51    Type(DeclRefTraitType),
52}
53
54impl DisplayWithEngines for TyTraitInterfaceItem {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
56        write!(f, "{:?}", engines.help_out(self))
57    }
58}
59
60impl DebugWithEngines for TyTraitInterfaceItem {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
62        write!(
63            f,
64            "TyTraitItem {}",
65            match self {
66                TyTraitInterfaceItem::TraitFn(fn_ref) => format!(
67                    "fn {:?}",
68                    engines.help_out(&*engines.de().get_trait_fn(fn_ref))
69                ),
70                TyTraitInterfaceItem::Constant(const_ref) => format!(
71                    "const {:?}",
72                    engines.help_out(&*engines.de().get_constant(const_ref))
73                ),
74                TyTraitInterfaceItem::Type(type_ref) => format!(
75                    "type {:?}",
76                    engines.help_out(&*engines.de().get_type(type_ref))
77                ),
78            }
79        )
80    }
81}
82
83#[derive(Clone, Debug, Serialize, Deserialize)]
84pub enum TyTraitItem {
85    Fn(DeclRefFunction),
86    Constant(DeclRefConstant),
87    Type(DeclRefTraitType),
88}
89
90impl DisplayWithEngines for TyTraitItem {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
92        write!(f, "{:?}", engines.help_out(self))
93    }
94}
95
96impl DebugWithEngines for TyTraitItem {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
98        write!(
99            f,
100            "TyTraitItem {}",
101            match self {
102                TyTraitItem::Fn(fn_ref) => format!(
103                    "fn {:?}",
104                    engines.help_out(&*engines.de().get_function(fn_ref))
105                ),
106                TyTraitItem::Constant(const_ref) => format!(
107                    "const {:?}",
108                    engines.help_out(&*engines.de().get_constant(const_ref))
109                ),
110                TyTraitItem::Type(type_ref) => format!(
111                    "type {:?}",
112                    engines.help_out(&*engines.de().get_type(type_ref))
113                ),
114            }
115        )
116    }
117}
118
119impl Named for TyTraitDecl {
120    fn name(&self) -> &Ident {
121        &self.name
122    }
123}
124
125impl Spanned for TyTraitDecl {
126    fn span(&self) -> Span {
127        self.span.clone()
128    }
129}
130
131impl EqWithEngines for TyTraitDecl {}
132impl PartialEqWithEngines for TyTraitDecl {
133    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
134        self.name == other.name
135            && self.type_parameters.eq(&other.type_parameters, ctx)
136            && self.interface_surface.eq(&other.interface_surface, ctx)
137            && self.items.eq(&other.items, ctx)
138            && self.supertraits.eq(&other.supertraits, ctx)
139            && self.visibility == other.visibility
140    }
141}
142
143impl HashWithEngines for TyTraitDecl {
144    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
145        let TyTraitDecl {
146            name,
147            type_parameters,
148            self_type,
149            interface_surface,
150            items,
151            supertraits,
152            visibility,
153            // these fields are not hashed because they aren't relevant/a
154            // reliable source of obj v. obj distinction
155            attributes: _,
156            span: _,
157            call_path: _,
158        } = self;
159        name.hash(state);
160        type_parameters.hash(state, engines);
161        self_type.hash(state, engines);
162        interface_surface.hash(state, engines);
163        items.hash(state, engines);
164        supertraits.hash(state, engines);
165        visibility.hash(state);
166    }
167}
168
169impl MaterializeConstGenerics for TyTraitDecl {
170    fn materialize_const_generics(
171        &mut self,
172        _engines: &Engines,
173        _handler: &Handler,
174        _name: &str,
175        _value: &crate::language::ty::TyExpression,
176    ) -> Result<(), ErrorEmitted> {
177        Ok(())
178    }
179}
180
181impl EqWithEngines for TyTraitInterfaceItem {}
182impl PartialEqWithEngines for TyTraitInterfaceItem {
183    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
184        match (self, other) {
185            (TyTraitInterfaceItem::TraitFn(id), TyTraitInterfaceItem::TraitFn(other_id)) => {
186                id.eq(other_id, ctx)
187            }
188            (TyTraitInterfaceItem::Constant(id), TyTraitInterfaceItem::Constant(other_id)) => {
189                id.eq(other_id, ctx)
190            }
191            _ => false,
192        }
193    }
194}
195
196impl EqWithEngines for TyTraitItem {}
197impl PartialEqWithEngines for TyTraitItem {
198    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
199        match (self, other) {
200            (TyTraitItem::Fn(id), TyTraitItem::Fn(other_id)) => id.eq(other_id, ctx),
201            (TyTraitItem::Constant(id), TyTraitItem::Constant(other_id)) => id.eq(other_id, ctx),
202            _ => false,
203        }
204    }
205}
206
207impl HashWithEngines for TyTraitInterfaceItem {
208    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
209        match self {
210            TyTraitInterfaceItem::TraitFn(fn_decl) => fn_decl.hash(state, engines),
211            TyTraitInterfaceItem::Constant(const_decl) => const_decl.hash(state, engines),
212            TyTraitInterfaceItem::Type(type_decl) => type_decl.hash(state, engines),
213        }
214    }
215}
216
217impl HashWithEngines for TyTraitItem {
218    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
219        match self {
220            TyTraitItem::Fn(fn_decl) => fn_decl.hash(state, engines),
221            TyTraitItem::Constant(const_decl) => const_decl.hash(state, engines),
222            TyTraitItem::Type(type_decl) => type_decl.hash(state, engines),
223        }
224    }
225}
226
227impl TypeCheckAnalysis for TyTraitItem {
228    fn type_check_analyze(
229        &self,
230        handler: &Handler,
231        ctx: &mut TypeCheckAnalysisContext,
232    ) -> Result<(), ErrorEmitted> {
233        let decl_engine = ctx.engines.de();
234
235        match self {
236            TyTraitItem::Fn(node) => {
237                node.type_check_analyze(handler, ctx)?;
238            }
239            TyTraitItem::Constant(node) => {
240                let item_const = decl_engine.get_constant(node);
241                item_const.type_check_analyze(handler, ctx)?;
242            }
243            TyTraitItem::Type(node) => {
244                let item_type = decl_engine.get_type(node);
245                item_type.type_check_analyze(handler, ctx)?;
246            }
247        }
248
249        Ok(())
250    }
251}
252
253impl TypeCheckFinalization for TyTraitItem {
254    fn type_check_finalize(
255        &mut self,
256        handler: &Handler,
257        ctx: &mut TypeCheckFinalizationContext,
258    ) -> Result<(), ErrorEmitted> {
259        let decl_engine = ctx.engines.de();
260        match self {
261            TyTraitItem::Fn(node) => {
262                let mut item_fn = (*decl_engine.get_function(node)).clone();
263                item_fn.type_check_finalize(handler, ctx)?;
264                decl_engine.replace(*node.id(), item_fn);
265            }
266            TyTraitItem::Constant(node) => {
267                let mut item_const = (*decl_engine.get_constant(node)).clone();
268                item_const.type_check_finalize(handler, ctx)?;
269                decl_engine.replace(*node.id(), item_const);
270            }
271            TyTraitItem::Type(_node) => {
272                // Nothing to finalize
273            }
274        }
275        Ok(())
276    }
277}
278
279impl Spanned for TyTraitItem {
280    fn span(&self) -> Span {
281        match self {
282            TyTraitItem::Fn(fn_decl) => fn_decl.span(),
283            TyTraitItem::Constant(const_decl) => const_decl.span(),
284            TyTraitItem::Type(type_decl) => type_decl.span(),
285        }
286    }
287}
288
289impl SubstTypes for TyTraitDecl {
290    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
291        has_changes! {
292            self.type_parameters.subst(ctx);
293            self.interface_surface
294                .iter_mut()
295                .fold(HasChanges::No, |has_changes, item| match item {
296                    TyTraitInterfaceItem::TraitFn(item_ref) => {
297                        if let Some(new_item_ref) = item_ref
298                            .clone()
299                            .subst_types_and_insert_new_with_parent(ctx) {
300                            item_ref.replace_id(*new_item_ref.id());
301                            HasChanges::Yes
302                        } else {
303                            HasChanges::No
304                        }
305                    }
306                    TyTraitInterfaceItem::Constant(decl_ref) => {
307                        if let Some(new_decl_ref) = decl_ref
308                            .clone()
309                            .subst_types_and_insert_new(ctx) {
310                            decl_ref.replace_id(*new_decl_ref.id());
311                            HasChanges::Yes
312                        } else{
313                            HasChanges::No
314                        }
315                    }
316                    TyTraitInterfaceItem::Type(decl_ref) => {
317                        if let Some(new_decl_ref) = decl_ref
318                            .clone()
319                            .subst_types_and_insert_new(ctx) {
320                            decl_ref.replace_id(*new_decl_ref.id());
321                            HasChanges::Yes
322                        } else{
323                            HasChanges::No
324                        }
325                    }
326                } | has_changes);
327            self.items.iter_mut().fold(HasChanges::No, |has_changes, item| match item {
328                TyTraitItem::Fn(item_ref) => {
329                    if let Some(new_item_ref) = item_ref
330                        .clone()
331                        .subst_types_and_insert_new_with_parent(ctx)
332                    {
333                        item_ref.replace_id(*new_item_ref.id());
334                        HasChanges::Yes
335                    } else {
336                        HasChanges::No
337                    }
338                }
339                TyTraitItem::Constant(item_ref) => {
340                    if let Some(new_decl_ref) = item_ref
341                        .clone()
342                        .subst_types_and_insert_new_with_parent(ctx)
343                    {
344                        item_ref.replace_id(*new_decl_ref.id());
345                        HasChanges::Yes
346                    } else {
347                        HasChanges::No
348                    }
349                }
350                TyTraitItem::Type(item_ref) => {
351                    if let Some(new_decl_ref) = item_ref
352                        .clone()
353                        .subst_types_and_insert_new_with_parent(ctx)
354                    {
355                        item_ref.replace_id(*new_decl_ref.id());
356                        HasChanges::Yes
357                    } else {
358                        HasChanges::No
359                    }
360                }
361            } | has_changes);
362        }
363    }
364}
365
366impl SubstTypes for TyTraitItem {
367    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
368        match self {
369            TyTraitItem::Fn(fn_decl) => fn_decl.subst(ctx),
370            TyTraitItem::Constant(const_decl) => const_decl.subst(ctx),
371            TyTraitItem::Type(type_decl) => type_decl.subst(ctx),
372        }
373    }
374}
375
376impl ReplaceFunctionImplementingType for TyTraitItem {
377    fn replace_implementing_type(&mut self, engines: &Engines, implementing_type: TyDecl) {
378        match self {
379            TyTraitItem::Fn(decl_ref) => {
380                decl_ref.replace_implementing_type(engines, implementing_type)
381            }
382            TyTraitItem::Constant(_decl_ref) => {
383                // ignore, only needed for functions
384            }
385            TyTraitItem::Type(_decl_ref) => {
386                // ignore, only needed for functions
387            }
388        }
389    }
390}
391
392impl MonomorphizeHelper for TyTraitDecl {
393    fn name(&self) -> &Ident {
394        &self.name
395    }
396
397    fn type_parameters(&self) -> &[TypeParameter] {
398        &self.type_parameters
399    }
400
401    fn has_self_type_param(&self) -> bool {
402        true
403    }
404}