Skip to main content

sway_core/language/ty/declaration/
impl_trait.rs

1use super::{TyAbiDecl, TyDeclParsedType, TyTraitDecl, TyTraitItem};
2use crate::{
3    decl_engine::{DeclId, DeclRefMixedInterface, InterfaceDeclId},
4    engine_threading::*,
5    has_changes,
6    language::{parsed::ImplSelfOrTrait, CallPath},
7    type_system::*,
8    HasChanges,
9};
10use serde::{Deserialize, Serialize};
11use std::{
12    fmt::Formatter,
13    hash::{Hash, Hasher},
14};
15use sway_types::{Ident, Named, Span, Spanned};
16
17pub type TyImplItem = TyTraitItem;
18
19/// Self impl, e.g.: `impl<A> Type<A>`,
20/// or trait impl, e.g.: `impl<A, B, C> Trait<A, B> for Type<C>`.
21#[derive(Clone, Debug, Serialize, Deserialize)]
22pub struct TyImplSelfOrTrait {
23    pub impl_type_parameters: Vec<TypeParameter>,
24    pub trait_name: CallPath,
25    pub trait_type_arguments: Vec<GenericArgument>,
26    pub items: Vec<TyImplItem>,
27    pub supertrait_items: Vec<TyImplItem>,
28    pub trait_decl_ref: Option<DeclRefMixedInterface>,
29    pub implementing_for: GenericTypeArgument,
30    pub span: Span,
31}
32
33impl TyImplSelfOrTrait {
34    pub fn is_impl_contract(&self, te: &TypeEngine) -> bool {
35        matches!(&*te.get(self.implementing_for.type_id), TypeInfo::Contract)
36    }
37
38    pub fn is_impl_self(&self) -> bool {
39        self.trait_decl_ref.is_none()
40    }
41
42    pub fn is_impl_trait(&self) -> bool {
43        match &self.trait_decl_ref {
44            Some(decl_ref) => matches!(decl_ref.id(), InterfaceDeclId::Trait(_)),
45            _ => false,
46        }
47    }
48
49    pub fn is_impl_abi(&self) -> bool {
50        match &self.trait_decl_ref {
51            Some(decl_ref) => matches!(decl_ref.id(), InterfaceDeclId::Abi(_)),
52            _ => false,
53        }
54    }
55
56    /// Returns [DeclId] of the trait implemented by `self`, if `self` implements a trait.
57    pub fn implemented_trait_decl_id(&self) -> Option<DeclId<TyTraitDecl>> {
58        match &self.trait_decl_ref {
59            Some(decl_ref) => match &decl_ref.id() {
60                InterfaceDeclId::Trait(decl_id) => Some(*decl_id),
61                InterfaceDeclId::Abi(_) => None,
62            },
63            _ => None,
64        }
65    }
66
67    /// Returns [DeclId] of the ABI implemented by `self`, if `self` implements an ABI for a contract.
68    pub fn implemented_abi_decl_id(&self) -> Option<DeclId<TyAbiDecl>> {
69        match &self.trait_decl_ref {
70            Some(decl_ref) => match &decl_ref.id() {
71                InterfaceDeclId::Abi(decl_id) => Some(*decl_id),
72                InterfaceDeclId::Trait(_) => None,
73            },
74            _ => None,
75        }
76    }
77}
78
79impl TyDeclParsedType for TyImplSelfOrTrait {
80    type ParsedType = ImplSelfOrTrait;
81}
82
83impl Named for TyImplSelfOrTrait {
84    fn name(&self) -> &Ident {
85        &self.trait_name.suffix
86    }
87}
88
89impl Spanned for TyImplSelfOrTrait {
90    fn span(&self) -> Span {
91        self.span.clone()
92    }
93}
94
95impl EqWithEngines for TyImplSelfOrTrait {}
96impl PartialEqWithEngines for TyImplSelfOrTrait {
97    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
98        self.impl_type_parameters
99            .eq(&other.impl_type_parameters, ctx)
100            && self.trait_name == other.trait_name
101            && self
102                .trait_type_arguments
103                .eq(&other.trait_type_arguments, ctx)
104            && self.items.eq(&other.items, ctx)
105            && self.implementing_for.eq(&other.implementing_for, ctx)
106            && self.trait_decl_ref.eq(&other.trait_decl_ref, ctx)
107    }
108}
109
110impl HashWithEngines for TyImplSelfOrTrait {
111    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
112        let TyImplSelfOrTrait {
113            impl_type_parameters,
114            trait_name,
115            trait_type_arguments,
116            items,
117            implementing_for,
118            trait_decl_ref,
119            // these fields are not hashed because they aren't relevant/a
120            // reliable source of obj v. obj distinction
121            span: _,
122            supertrait_items: _,
123        } = self;
124        trait_name.hash(state);
125        impl_type_parameters.hash(state, engines);
126        trait_type_arguments.hash(state, engines);
127        items.hash(state, engines);
128        implementing_for.hash(state, engines);
129        trait_decl_ref.hash(state, engines);
130    }
131}
132
133impl SubstTypes for TyImplSelfOrTrait {
134    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
135        has_changes! {
136            self.impl_type_parameters.subst(ctx);
137            self.implementing_for.subst_inner(ctx);
138            self.items.subst(ctx);
139        }
140    }
141}
142
143impl DebugWithEngines for TyImplSelfOrTrait {
144    fn fmt(&self, f: &mut Formatter<'_>, engines: &Engines) -> std::fmt::Result {
145        if let Some(t) = self.trait_decl_ref.as_ref() {
146            write!(
147                f,
148                "impl<> {:?} for {:?} -> {:?}",
149                t.name().as_str(),
150                engines.help_out(self.implementing_for.initial_type_id),
151                engines.help_out(self.implementing_for.type_id),
152            )
153        } else {
154            write!(
155                f,
156                "impl<> {:?} -> {:?}",
157                engines.help_out(self.implementing_for.initial_type_id),
158                engines.help_out(self.implementing_for.type_id),
159            )
160        }
161    }
162}