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