Skip to main content

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