1use crate::{
2 decl_engine::*,
3 engine_threading::*,
4 language::ty::*,
5 semantic_analysis::{
6 TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext, TypeCheckFinalization,
7 TypeCheckFinalizationContext,
8 },
9 transform::{AllowDeprecatedState, AttributeKind},
10 type_system::*,
11 types::*,
12};
13use serde::{Deserialize, Serialize};
14use std::{
15 fmt::{self, Debug},
16 hash::{Hash, Hasher},
17};
18use sway_error::handler::{ErrorEmitted, Handler};
19use sway_types::{Ident, Span};
20
21pub trait GetDeclIdent {
22 fn get_decl_ident(&self, engines: &Engines) -> Option<Ident>;
23}
24
25#[derive(Clone, Debug, Serialize, Deserialize)]
26pub struct TyAstNode {
27 pub content: TyAstNodeContent,
28 pub span: Span,
29}
30
31impl EqWithEngines for TyAstNode {}
32impl PartialEqWithEngines for TyAstNode {
33 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
34 self.content.eq(&other.content, ctx)
35 }
36}
37
38impl HashWithEngines for TyAstNode {
39 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
40 let TyAstNode {
41 content,
42 span: _,
45 } = self;
46 content.hash(state, engines);
47 }
48}
49
50impl DebugWithEngines for TyAstNode {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
52 use TyAstNodeContent::*;
53 match &self.content {
54 Declaration(typed_decl) => DebugWithEngines::fmt(typed_decl, f, engines),
55 Expression(exp) => DebugWithEngines::fmt(exp, f, engines),
56 SideEffect(_) => f.write_str(""),
57 Error(_, _) => f.write_str("error"),
58 }
59 }
60}
61
62impl SubstTypes for TyAstNode {
63 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
64 match self.content {
65 TyAstNodeContent::Declaration(ref mut decl) => decl.subst(ctx),
66 TyAstNodeContent::Expression(ref mut expr) => expr.subst(ctx),
67 TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => HasChanges::No,
68 }
69 }
70}
71
72impl ReplaceDecls for TyAstNode {
73 fn replace_decls_inner(
74 &mut self,
75 decl_mapping: &DeclMapping,
76 handler: &Handler,
77 ctx: &mut TypeCheckContext,
78 ) -> Result<bool, ErrorEmitted> {
79 match self.content {
80 TyAstNodeContent::Declaration(TyDecl::VariableDecl(ref mut decl)) => {
81 decl.body.replace_decls(decl_mapping, handler, ctx)
82 }
83 TyAstNodeContent::Declaration(TyDecl::ConstantDecl(ref mut decl)) => {
84 decl.replace_decls(decl_mapping, handler, ctx)
85 }
86 TyAstNodeContent::Declaration(_) => Ok(false),
87 TyAstNodeContent::Expression(ref mut expr) => {
88 expr.replace_decls(decl_mapping, handler, ctx)
89 }
90 TyAstNodeContent::SideEffect(_) => Ok(false),
91 TyAstNodeContent::Error(_, _) => Ok(false),
92 }
93 }
94}
95
96impl UpdateConstantExpression for TyAstNode {
97 fn update_constant_expression(&mut self, engines: &Engines, implementing_type: &TyDecl) {
98 match self.content {
99 TyAstNodeContent::Declaration(_) => {}
100 TyAstNodeContent::Expression(ref mut expr) => {
101 expr.update_constant_expression(engines, implementing_type)
102 }
103 TyAstNodeContent::SideEffect(_) => (),
104 TyAstNodeContent::Error(_, _) => (),
105 }
106 }
107}
108
109impl TypeCheckAnalysis for TyAstNode {
110 fn type_check_analyze(
111 &self,
112 handler: &Handler,
113 ctx: &mut TypeCheckAnalysisContext,
114 ) -> Result<(), ErrorEmitted> {
115 self.content.type_check_analyze(handler, ctx)
116 }
117}
118
119impl TypeCheckFinalization for TyAstNode {
120 fn type_check_finalize(
121 &mut self,
122 handler: &Handler,
123 ctx: &mut TypeCheckFinalizationContext,
124 ) -> Result<(), ErrorEmitted> {
125 self.content.type_check_finalize(handler, ctx)
126 }
127}
128
129impl CollectTypesMetadata for TyAstNode {
130 fn collect_types_metadata(
131 &self,
132 handler: &Handler,
133 ctx: &mut CollectTypesMetadataContext,
134 ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
135 self.content.collect_types_metadata(handler, ctx)
136 }
137}
138
139impl GetDeclIdent for TyAstNode {
140 fn get_decl_ident(&self, engines: &Engines) -> Option<Ident> {
141 self.content.get_decl_ident(engines)
142 }
143}
144
145impl MaterializeConstGenerics for TyAstNode {
146 fn materialize_const_generics(
147 &mut self,
148 engines: &Engines,
149 handler: &Handler,
150 name: &str,
151 value: &TyExpression,
152 ) -> Result<(), ErrorEmitted> {
153 match &mut self.content {
154 TyAstNodeContent::Declaration(TyDecl::ConstantDecl(constant_decl)) => {
155 let decl = engines.de().get(&constant_decl.decl_id);
156
157 let mut decl = TyConstantDecl::clone(&*decl);
158 decl.materialize_const_generics(engines, handler, name, value)?;
159
160 let r = engines.de().insert(decl, None);
161 *constant_decl = ConstantDecl { decl_id: *r.id() };
162
163 Ok(())
164 }
165 TyAstNodeContent::Declaration(TyDecl::VariableDecl(decl)) => {
166 decl.body
167 .materialize_const_generics(engines, handler, name, value)?;
168 decl.return_type
169 .materialize_const_generics(engines, handler, name, value)?;
170 decl.type_ascription
171 .type_id
172 .materialize_const_generics(engines, handler, name, value)?;
173 Ok(())
174 }
175 TyAstNodeContent::Expression(expr) => {
176 expr.materialize_const_generics(engines, handler, name, value)
177 }
178 _ => Ok(()),
179 }
180 }
181}
182
183impl TyAstNode {
184 pub(crate) fn is_public(&self, decl_engine: &DeclEngine) -> bool {
186 match &self.content {
187 TyAstNodeContent::Declaration(decl) => decl.visibility(decl_engine).is_public(),
188 TyAstNodeContent::Expression(_)
189 | TyAstNodeContent::SideEffect(_)
190 | TyAstNodeContent::Error(_, _) => false,
191 }
192 }
193
194 pub(crate) fn is_generic_function(&self, decl_engine: &DeclEngine) -> bool {
196 match &self {
197 TyAstNode {
198 span: _,
199 content:
200 TyAstNodeContent::Declaration(TyDecl::FunctionDecl(FunctionDecl {
201 decl_id, ..
202 })),
203 ..
204 } => {
205 let fn_decl = decl_engine.get_function(decl_id);
206 let TyFunctionDecl {
207 type_parameters, ..
208 } = &*fn_decl;
209 !type_parameters.is_empty()
210 }
211 _ => false,
212 }
213 }
214
215 pub(crate) fn is_test_function(&self, decl_engine: &DeclEngine) -> bool {
217 match &self {
218 TyAstNode {
219 span: _,
220 content:
221 TyAstNodeContent::Declaration(TyDecl::FunctionDecl(FunctionDecl {
222 decl_id, ..
223 })),
224 ..
225 } => {
226 let fn_decl = decl_engine.get_function(decl_id);
227 let TyFunctionDecl { attributes, .. } = &*fn_decl;
228 attributes.has_any_of_kind(AttributeKind::Test)
229 }
230 _ => false,
231 }
232 }
233
234 pub(crate) fn type_info(&self, type_engine: &TypeEngine) -> TypeInfo {
235 match &self.content {
237 TyAstNodeContent::Declaration(_) => TypeInfo::Tuple(Vec::new()),
238 TyAstNodeContent::Expression(TyExpression { return_type, .. }) => {
239 (*type_engine.get(*return_type)).clone()
240 }
241 TyAstNodeContent::SideEffect(_) => TypeInfo::Tuple(Vec::new()),
242 TyAstNodeContent::Error(_, error) => TypeInfo::ErrorRecovery(*error),
243 }
244 }
245
246 pub(crate) fn check_deprecated(
247 &self,
248 engines: &Engines,
249 handler: &Handler,
250 allow_deprecated: &mut AllowDeprecatedState,
251 ) {
252 match &self.content {
253 TyAstNodeContent::Declaration(node) => match node {
254 TyDecl::VariableDecl(decl) => {
255 decl.body
256 .check_deprecated(engines, handler, allow_deprecated);
257 }
258 TyDecl::ConstantDecl(decl) => {
259 let decl = engines.de().get(&decl.decl_id);
260 if let Some(value) = &decl.value {
261 value.check_deprecated(engines, handler, allow_deprecated);
262 }
263 }
264 TyDecl::ConfigurableDecl(decl) => {
265 let decl = engines.de().get(&decl.decl_id);
266 if let Some(value) = &decl.value {
267 value.check_deprecated(engines, handler, allow_deprecated);
268 }
269 }
270 TyDecl::ConstGenericDecl(_) => {
271 unreachable!("ConstGenericDecl is not reachable from AstNode")
272 }
273 TyDecl::TraitTypeDecl(_) => {}
274 TyDecl::FunctionDecl(decl) => {
275 let decl = engines.de().get(&decl.decl_id);
276 let token = allow_deprecated.enter(decl.attributes.clone());
277 for node in decl.body.contents.iter() {
278 node.check_deprecated(engines, handler, allow_deprecated);
279 }
280 allow_deprecated.exit(token);
281 }
282 TyDecl::ImplSelfOrTrait(decl) => {
283 let decl = engines.de().get(&decl.decl_id);
284 for item in decl.items.iter() {
285 match item {
286 TyTraitItem::Fn(item) => {
287 let decl = engines.de().get(item.id());
288 let token = allow_deprecated.enter(decl.attributes.clone());
289 for node in decl.body.contents.iter() {
290 node.check_deprecated(engines, handler, allow_deprecated);
291 }
292 allow_deprecated.exit(token);
293 }
294 TyTraitItem::Constant(item) => {
295 let decl = engines.de().get(item.id());
296 if let Some(expr) = decl.value.as_ref() {
297 expr.check_deprecated(engines, handler, allow_deprecated);
298 }
299 }
300 TyTraitItem::Type(_) => {}
301 }
302 }
303 }
304 TyDecl::AbiDecl(_)
305 | TyDecl::GenericTypeForFunctionScope(_)
306 | TyDecl::ErrorRecovery(_, _)
307 | TyDecl::StorageDecl(_)
308 | TyDecl::TraitDecl(_)
309 | TyDecl::StructDecl(_)
310 | TyDecl::EnumDecl(_)
311 | TyDecl::EnumVariantDecl(_)
312 | TyDecl::TypeAliasDecl(_) => {}
313 },
314 TyAstNodeContent::Expression(node) => {
315 node.check_deprecated(engines, handler, allow_deprecated);
316 }
317 TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {}
318 }
319 }
320
321 pub(crate) fn check_recursive(
322 &self,
323 engines: &Engines,
324 handler: &Handler,
325 ) -> Result<(), ErrorEmitted> {
326 handler.scope(|handler| {
327 match &self.content {
328 TyAstNodeContent::Declaration(node) => match node {
329 TyDecl::VariableDecl(_decl) => {}
330 TyDecl::ConstantDecl(_decl) => {}
331 TyDecl::ConfigurableDecl(_decl) => {}
332 TyDecl::ConstGenericDecl(_decl) => {
333 unreachable!("ConstGenericDecl is not reachable from AstNode")
334 }
335 TyDecl::TraitTypeDecl(_) => {}
336 TyDecl::FunctionDecl(decl) => {
337 let fn_decl_id = decl.decl_id;
338 let mut ctx = TypeCheckAnalysisContext::new(engines);
339 let _ = fn_decl_id.type_check_analyze(handler, &mut ctx);
340 let _ = ctx.check_recursive_calls(handler);
341 }
342 TyDecl::ImplSelfOrTrait(decl) => {
343 let decl = engines.de().get(&decl.decl_id);
344 for item in decl.items.iter() {
345 let mut ctx = TypeCheckAnalysisContext::new(engines);
346 let _ = item.type_check_analyze(handler, &mut ctx);
347 let _ = ctx.check_recursive_calls(handler);
348 }
349 }
350 TyDecl::AbiDecl(_)
351 | TyDecl::GenericTypeForFunctionScope(_)
352 | TyDecl::ErrorRecovery(_, _)
353 | TyDecl::StorageDecl(_)
354 | TyDecl::TraitDecl(_)
355 | TyDecl::StructDecl(_)
356 | TyDecl::EnumDecl(_)
357 | TyDecl::EnumVariantDecl(_)
358 | TyDecl::TypeAliasDecl(_) => {}
359 },
360 TyAstNodeContent::Expression(_node) => {}
361 TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {}
362 };
363 Ok(())
364 })
365 }
366
367 pub fn contract_supertrait_fns(&self, engines: &Engines) -> Vec<DeclId<TyFunctionDecl>> {
368 let mut fns = vec![];
369
370 if let TyAstNodeContent::Declaration(TyDecl::ImplSelfOrTrait(decl)) = &self.content {
371 let decl = engines.de().get(&decl.decl_id);
372 if decl.is_impl_contract(engines.te()) {
373 for item in &decl.supertrait_items {
374 if let TyTraitItem::Fn(f) = item {
375 fns.push(*f.id());
376 }
377 }
378 }
379 }
380
381 fns
382 }
383
384 pub fn contract_fns(&self, engines: &Engines) -> Vec<DeclId<TyFunctionDecl>> {
385 let mut fns = vec![];
386
387 if let TyAstNodeContent::Declaration(TyDecl::ImplSelfOrTrait(decl)) = &self.content {
388 let decl = engines.de().get(&decl.decl_id);
389 if decl.is_impl_contract(engines.te()) {
390 for item in &decl.items {
391 if let TyTraitItem::Fn(f) = item {
392 fns.push(*f.id());
393 }
394 }
395 }
396 }
397
398 fns
399 }
400}
401
402#[derive(Clone, Debug, Serialize, Deserialize)]
403#[allow(clippy::large_enum_variant)]
404pub enum TyAstNodeContent {
405 Declaration(TyDecl),
406 Expression(TyExpression),
407 SideEffect(TySideEffect),
409 Error(Box<[Span]>, #[serde(skip)] ErrorEmitted),
410}
411
412impl EqWithEngines for TyAstNodeContent {}
413impl PartialEqWithEngines for TyAstNodeContent {
414 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
415 match (self, other) {
416 (Self::Declaration(x), Self::Declaration(y)) => x.eq(y, ctx),
417 (Self::Expression(x), Self::Expression(y)) => x.eq(y, ctx),
418 (Self::SideEffect(_), Self::SideEffect(_)) => true,
419 _ => false,
420 }
421 }
422}
423
424impl HashWithEngines for TyAstNodeContent {
425 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
426 use TyAstNodeContent::*;
427 std::mem::discriminant(self).hash(state);
428 match self {
429 Declaration(decl) => {
430 decl.hash(state, engines);
431 }
432 Expression(exp) => {
433 exp.hash(state, engines);
434 }
435 SideEffect(effect) => {
436 effect.hash(state);
437 }
438 Error(_, _) => {}
439 }
440 }
441}
442
443impl TypeCheckAnalysis for TyAstNodeContent {
444 fn type_check_analyze(
445 &self,
446 handler: &Handler,
447 ctx: &mut TypeCheckAnalysisContext,
448 ) -> Result<(), ErrorEmitted> {
449 match self {
450 TyAstNodeContent::Declaration(node) => node.type_check_analyze(handler, ctx)?,
451 TyAstNodeContent::Expression(node) => node.type_check_analyze(handler, ctx)?,
452 TyAstNodeContent::SideEffect(_) => {}
453 TyAstNodeContent::Error(_, _) => {}
454 }
455 Ok(())
456 }
457}
458
459impl TypeCheckFinalization for TyAstNodeContent {
460 fn type_check_finalize(
461 &mut self,
462 handler: &Handler,
463 ctx: &mut TypeCheckFinalizationContext,
464 ) -> Result<(), ErrorEmitted> {
465 match self {
466 TyAstNodeContent::Declaration(node) => node.type_check_finalize(handler, ctx)?,
467 TyAstNodeContent::Expression(node) => node.type_check_finalize(handler, ctx)?,
468 TyAstNodeContent::SideEffect(_) => {}
469 TyAstNodeContent::Error(_, _) => {}
470 }
471 Ok(())
472 }
473}
474
475impl CollectTypesMetadata for TyAstNodeContent {
476 fn collect_types_metadata(
477 &self,
478 handler: &Handler,
479 ctx: &mut CollectTypesMetadataContext,
480 ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
481 use TyAstNodeContent::*;
482 match self {
483 Declaration(decl) => decl.collect_types_metadata(handler, ctx),
484 Expression(expr) => expr.collect_types_metadata(handler, ctx),
485 SideEffect(_) => Ok(vec![]),
486 Error(_, _) => Ok(vec![]),
487 }
488 }
489}
490
491impl GetDeclIdent for TyAstNodeContent {
492 fn get_decl_ident(&self, engines: &Engines) -> Option<Ident> {
493 match self {
494 TyAstNodeContent::Declaration(decl) => decl.get_decl_ident(engines),
495 TyAstNodeContent::Expression(_expr) => None, TyAstNodeContent::SideEffect(_) => None,
497 TyAstNodeContent::Error(_, _) => None,
498 }
499 }
500}