1use crate::{
2 decl_engine::{
3 DeclEngineInsert, 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<HasChanges, ErrorEmitted> {
260 let decl_engine = ctx.engines.de();
261 let has_changes = match self {
262 TyTraitItem::Fn(node) => {
263 let mut item_fn = (*decl_engine.get_function(node)).clone();
264 let has_changes = item_fn.type_check_finalize(handler, ctx)?;
265 if has_changes.has_changes() {
266 *node = decl_engine.insert_modified(item_fn, *node.id())
267 }
268 has_changes
269 }
270 TyTraitItem::Constant(node) => {
271 let mut item_const = (*decl_engine.get_constant(node)).clone();
272 let has_changes = item_const.type_check_finalize(handler, ctx)?;
273 if has_changes.has_changes() {
274 *node = decl_engine.insert_modified(item_const, *node.id())
275 }
276 has_changes
277 }
278 TyTraitItem::Type(_node) => HasChanges::No,
279 };
280 Ok(has_changes)
281 }
282}
283
284impl Spanned for TyTraitItem {
285 fn span(&self) -> Span {
286 match self {
287 TyTraitItem::Fn(fn_decl) => fn_decl.span(),
288 TyTraitItem::Constant(const_decl) => const_decl.span(),
289 TyTraitItem::Type(type_decl) => type_decl.span(),
290 }
291 }
292}
293
294impl SubstTypes for TyTraitDecl {
295 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
296 has_changes! {
297 self.type_parameters.subst(ctx);
298 self.interface_surface
299 .iter_mut()
300 .fold(HasChanges::No, |has_changes, item| match item {
301 TyTraitInterfaceItem::TraitFn(item_ref) => {
302 if let Some(new_item_ref) = item_ref
303 .clone()
304 .subst_types_and_insert_new_with_parent(ctx) {
305 item_ref.replace_id(*new_item_ref.id());
306 HasChanges::Yes
307 } else {
308 HasChanges::No
309 }
310 }
311 TyTraitInterfaceItem::Constant(decl_ref) => {
312 if let Some(new_decl_ref) = decl_ref
313 .clone()
314 .subst_types_and_insert_new(ctx) {
315 decl_ref.replace_id(*new_decl_ref.id());
316 HasChanges::Yes
317 } else{
318 HasChanges::No
319 }
320 }
321 TyTraitInterfaceItem::Type(decl_ref) => {
322 if let Some(new_decl_ref) = decl_ref
323 .clone()
324 .subst_types_and_insert_new(ctx) {
325 decl_ref.replace_id(*new_decl_ref.id());
326 HasChanges::Yes
327 } else{
328 HasChanges::No
329 }
330 }
331 } | has_changes);
332 self.items.iter_mut().fold(HasChanges::No, |has_changes, item| match item {
333 TyTraitItem::Fn(item_ref) => {
334 if let Some(new_item_ref) = item_ref
335 .clone()
336 .subst_types_and_insert_new_with_parent(ctx)
337 {
338 item_ref.replace_id(*new_item_ref.id());
339 HasChanges::Yes
340 } else {
341 HasChanges::No
342 }
343 }
344 TyTraitItem::Constant(item_ref) => {
345 if let Some(new_decl_ref) = item_ref
346 .clone()
347 .subst_types_and_insert_new_with_parent(ctx)
348 {
349 item_ref.replace_id(*new_decl_ref.id());
350 HasChanges::Yes
351 } else {
352 HasChanges::No
353 }
354 }
355 TyTraitItem::Type(item_ref) => {
356 if let Some(new_decl_ref) = item_ref
357 .clone()
358 .subst_types_and_insert_new_with_parent(ctx)
359 {
360 item_ref.replace_id(*new_decl_ref.id());
361 HasChanges::Yes
362 } else {
363 HasChanges::No
364 }
365 }
366 } | has_changes);
367 }
368 }
369}
370
371impl SubstTypes for TyTraitItem {
372 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
373 match self {
374 TyTraitItem::Fn(fn_decl) => fn_decl.subst(ctx),
375 TyTraitItem::Constant(const_decl) => const_decl.subst(ctx),
376 TyTraitItem::Type(type_decl) => type_decl.subst(ctx),
377 }
378 }
379}
380
381impl ReplaceFunctionImplementingType for TyTraitItem {
382 fn replace_implementing_type(&mut self, engines: &Engines, implementing_type: TyDecl) {
383 match self {
384 TyTraitItem::Fn(decl_ref) => {
385 decl_ref.replace_implementing_type(engines, implementing_type)
386 }
387 TyTraitItem::Constant(_decl_ref) => {
388 }
390 TyTraitItem::Type(_decl_ref) => {
391 }
393 }
394 }
395}
396
397impl MonomorphizeHelper for TyTraitDecl {
398 fn name(&self) -> &Ident {
399 &self.name
400 }
401
402 fn type_parameters(&self) -> &[TypeParameter] {
403 &self.type_parameters
404 }
405
406 fn has_self_type_param(&self) -> bool {
407 true
408 }
409}