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 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 }
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 }
386 TyTraitItem::Type(_decl_ref) => {
387 }
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}