1use crate::{
2 decl_engine::*,
3 engine_threading::*,
4 has_changes,
5 language::{ty::*, Literal},
6 semantic_analysis::{
7 TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext, TypeCheckFinalization,
8 TypeCheckFinalizationContext,
9 },
10 transform::{AllowDeprecatedState, Attributes},
11 type_system::*,
12 types::*,
13 HasChanges,
14};
15use serde::{Deserialize, Serialize};
16use std::{fmt, hash::Hasher};
17use sway_error::{
18 error::CompileError,
19 handler::{ErrorEmitted, Handler},
20 type_error::TypeError,
21 warning::{CompileWarning, DeprecatedElement, Warning},
22};
23use sway_types::{Span, Spanned};
24
25#[derive(Clone, Debug, Serialize, Deserialize)]
26pub struct TyExpression {
27 pub expression: TyExpressionVariant,
28 pub return_type: TypeId,
29 pub span: Span,
30}
31
32impl EqWithEngines for TyExpression {}
33impl PartialEqWithEngines for TyExpression {
34 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
35 let type_engine = ctx.engines().te();
36 self.expression.eq(&other.expression, ctx)
37 && type_engine
38 .get(self.return_type)
39 .eq(&type_engine.get(other.return_type), ctx)
40 }
41}
42
43impl HashWithEngines for TyExpression {
44 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
45 let TyExpression {
46 expression,
47 return_type,
48 span: _,
51 } = self;
52 let type_engine = engines.te();
53 expression.hash(state, engines);
54 type_engine.get(*return_type).hash(state, engines);
55 }
56}
57
58impl SubstTypes for TyExpression {
59 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
60 has_changes! {
61 self.return_type.subst(ctx);
62 self.expression.subst(ctx);
63 }
64 }
65}
66
67impl ReplaceDecls for TyExpression {
68 fn replace_decls_inner(
69 &mut self,
70 decl_mapping: &DeclMapping,
71 handler: &Handler,
72 ctx: &mut TypeCheckContext,
73 ) -> Result<HasChanges, ErrorEmitted> {
74 self.expression.replace_decls(decl_mapping, handler, ctx)
75 }
76}
77
78impl UpdateConstantExpression for TyExpression {
79 fn update_constant_expression(
80 &mut self,
81 engines: &Engines,
82 implementing_type: &TyDecl,
83 ) -> HasChanges {
84 self.expression
85 .update_constant_expression(engines, implementing_type)
86 }
87}
88
89impl DisplayWithEngines for TyExpression {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
91 write!(
92 f,
93 "{} ({})",
94 engines.help_out(&self.expression),
95 engines.help_out(self.return_type)
96 )
97 }
98}
99
100impl DebugWithEngines for TyExpression {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
102 write!(
103 f,
104 "{:?} ({:?})",
105 engines.help_out(&self.expression),
106 engines.help_out(self.return_type)
107 )
108 }
109}
110
111impl TypeCheckAnalysis for TyExpression {
112 fn type_check_analyze(
113 &self,
114 handler: &Handler,
115 ctx: &mut TypeCheckAnalysisContext,
116 ) -> Result<(), ErrorEmitted> {
117 match &self.expression {
118 TyExpressionVariant::Literal(Literal::Numeric(literal_value)) => {
120 let t = ctx.engines.te().get(self.return_type);
121 if let TypeInfo::UnsignedInteger(bits) = &*t {
122 if bits.would_overflow(*literal_value) {
123 handler.emit_err(CompileError::TypeError(TypeError::LiteralOverflow {
124 expected: format!("{:?}", ctx.engines.help_out(t)),
125 span: self.span.clone(),
126 }));
127 }
128 }
129 }
130 TyExpressionVariant::ArrayExplicit { .. } => {
131 self.as_array_unify_elements(handler, ctx.engines);
132 }
133 _ => {}
134 }
135 self.expression.type_check_analyze(handler, ctx)
136 }
137}
138
139impl TypeCheckFinalization for TyExpression {
140 fn type_check_finalize(
141 &mut self,
142 handler: &Handler,
143 ctx: &mut TypeCheckFinalizationContext,
144 ) -> Result<HasChanges, ErrorEmitted> {
145 let mut has_changes = self.expression.type_check_finalize(handler, ctx)?;
146 if let TyExpressionVariant::FunctionApplication { fn_ref, .. } = &self.expression {
147 let method = ctx.engines.de().get_function(fn_ref);
148 let new_return_type = method.return_type.type_id;
149 has_changes |= HasChanges::from(self.return_type != new_return_type);
150 self.return_type = new_return_type;
151 }
152 Ok(has_changes)
153 }
154}
155
156impl CollectTypesMetadata for TyExpression {
157 fn collect_types_metadata(
158 &self,
159 handler: &Handler,
160 ctx: &mut CollectTypesMetadataContext,
161 ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
162 use TyExpressionVariant::*;
163 let decl_engine = ctx.engines.de();
164 let mut res = self.return_type.collect_types_metadata(handler, ctx)?;
165 match &self.expression {
166 FunctionApplication {
167 arguments,
168 fn_ref,
169 call_path,
170 type_binding,
171 ..
172 } => {
173 for arg in arguments.iter() {
174 res.append(&mut arg.1.collect_types_metadata(handler, ctx)?);
175 }
176 let function_decl = decl_engine.get_function(fn_ref);
177
178 ctx.call_site_push();
179 for (idx, p) in function_decl
180 .type_parameters
181 .iter()
182 .filter_map(|x| x.as_type_parameter())
183 .enumerate()
184 {
185 ctx.call_site_insert(p.type_id, call_path.span());
186
187 res.extend(
189 p.type_id
190 .collect_types_metadata(handler, ctx)?
191 .into_iter()
192 .map(|x| match x {
194 TypeMetadata::UnresolvedType(ident, original_span) => {
195 let span = type_binding
196 .as_ref()
197 .and_then(|type_binding| {
198 type_binding.type_arguments.as_slice().get(idx)
199 })
200 .map(|type_argument| Some(type_argument.span()))
201 .unwrap_or(original_span);
202 TypeMetadata::UnresolvedType(ident, span)
203 }
204 x => x,
205 }),
206 );
207 }
208
209 for content in function_decl.body.contents.iter() {
210 res.append(&mut content.collect_types_metadata(handler, ctx)?);
211 }
212 ctx.call_site_pop();
213 }
214 Tuple { fields } => {
215 for field in fields.iter() {
216 res.append(&mut field.collect_types_metadata(handler, ctx)?);
217 }
218 }
219 AsmExpression { registers, .. } => {
220 for register in registers.iter() {
221 if let Some(init) = register.initializer.as_ref() {
222 res.append(&mut init.collect_types_metadata(handler, ctx)?);
223 }
224 }
225 }
226 StructExpression {
227 fields,
228 instantiation_span,
229 struct_id,
230 ..
231 } => {
232 let struct_decl = decl_engine.get_struct(struct_id);
233 for p in &struct_decl.generic_parameters {
234 match p {
235 TypeParameter::Type(p) => {
236 ctx.call_site_insert(p.type_id, instantiation_span.clone());
237 }
238 TypeParameter::Const(_) => {}
239 }
240 }
241 if let TypeInfo::Struct(decl_ref) = &*ctx.engines.te().get(self.return_type) {
242 let decl = decl_engine.get_struct(decl_ref);
243 for p in &decl.generic_parameters {
244 match p {
245 TypeParameter::Type(p) => {
246 ctx.call_site_insert(p.type_id, instantiation_span.clone());
247 }
248 TypeParameter::Const(_) => {}
249 }
250 }
251 }
252 for field in fields.iter() {
253 res.append(&mut field.value.collect_types_metadata(handler, ctx)?);
254 }
255 }
256 LazyOperator { lhs, rhs, .. } => {
257 res.append(&mut lhs.collect_types_metadata(handler, ctx)?);
258 res.append(&mut rhs.collect_types_metadata(handler, ctx)?);
259 }
260 ArrayExplicit {
261 elem_type: _,
262 contents,
263 } => {
264 for content in contents.iter() {
265 res.append(&mut content.collect_types_metadata(handler, ctx)?);
266 }
267 }
268 ArrayRepeat {
269 elem_type: _,
270 value,
271 length,
272 } => {
273 res.append(&mut value.collect_types_metadata(handler, ctx)?);
274 res.append(&mut length.collect_types_metadata(handler, ctx)?);
275 }
276 ArrayIndex { prefix, index } => {
277 res.append(&mut (**prefix).collect_types_metadata(handler, ctx)?);
278 res.append(&mut (**index).collect_types_metadata(handler, ctx)?);
279 }
280 CodeBlock(block) => {
281 for content in block.contents.iter() {
282 res.append(&mut content.collect_types_metadata(handler, ctx)?);
283 }
284 }
285 MatchExp { desugared, .. } => {
286 res.append(&mut desugared.collect_types_metadata(handler, ctx)?)
287 }
288 IfExp {
289 condition,
290 then,
291 r#else,
292 } => {
293 res.append(&mut condition.collect_types_metadata(handler, ctx)?);
294 res.append(&mut then.collect_types_metadata(handler, ctx)?);
295 if let Some(r#else) = r#else {
296 res.append(&mut r#else.collect_types_metadata(handler, ctx)?);
297 }
298 }
299 StructFieldAccess {
300 prefix,
301 resolved_type_of_parent,
302 ..
303 } => {
304 res.append(&mut prefix.collect_types_metadata(handler, ctx)?);
305 res.append(&mut resolved_type_of_parent.collect_types_metadata(handler, ctx)?);
306 }
307 TupleElemAccess {
308 prefix,
309 resolved_type_of_parent,
310 ..
311 } => {
312 res.append(&mut prefix.collect_types_metadata(handler, ctx)?);
313 res.append(&mut resolved_type_of_parent.collect_types_metadata(handler, ctx)?);
314 }
315 EnumInstantiation {
316 enum_ref,
317 contents,
318 call_path_binding,
319 ..
320 } => {
321 let enum_decl = decl_engine.get_enum(enum_ref);
322 for p in enum_decl.generic_parameters.iter() {
323 match p {
324 TypeParameter::Type(p) => {
325 ctx.call_site_insert(p.type_id, call_path_binding.inner.suffix.span())
326 }
327 TypeParameter::Const(_) => {}
328 }
329 }
330 if let Some(contents) = contents {
331 res.append(&mut contents.collect_types_metadata(handler, ctx)?);
332 }
333 for variant in enum_decl.variants.iter() {
334 res.append(
335 &mut variant
336 .type_argument
337 .type_id
338 .collect_types_metadata(handler, ctx)?,
339 );
340 }
341 for p in enum_decl.generic_parameters.iter() {
342 match p {
343 TypeParameter::Type(p) => {
344 res.append(&mut p.type_id.collect_types_metadata(handler, ctx)?);
345 }
346 TypeParameter::Const(_) => {}
347 }
348 }
349 }
350 AbiCast { address, .. } => {
351 res.append(&mut address.collect_types_metadata(handler, ctx)?);
352 }
353 IntrinsicFunction(kind) => {
354 res.append(&mut kind.collect_types_metadata(handler, ctx)?);
355 }
356 EnumTag { exp } => {
357 res.append(&mut exp.collect_types_metadata(handler, ctx)?);
358 }
359 UnsafeDowncast {
360 exp,
361 variant,
362 call_path_decl: _,
363 } => {
364 res.append(&mut exp.collect_types_metadata(handler, ctx)?);
365 res.append(
366 &mut variant
367 .type_argument
368 .type_id
369 .collect_types_metadata(handler, ctx)?,
370 );
371 }
372 WhileLoop { condition, body } => {
373 res.append(&mut condition.collect_types_metadata(handler, ctx)?);
374 for content in body.contents.iter() {
375 res.append(&mut content.collect_types_metadata(handler, ctx)?);
376 }
377 }
378 ForLoop { desugared } => {
379 res.append(&mut desugared.collect_types_metadata(handler, ctx)?);
380 }
381 ImplicitReturn(exp) | Return(exp) => {
382 res.append(&mut exp.collect_types_metadata(handler, ctx)?)
383 }
384 Panic(exp) => {
385 let logged_type_id =
387 TypeMetadata::get_logged_type_id(exp, ctx.experimental.new_encoding)
388 .map_err(|err| handler.emit_err(err))?;
389 res.push(TypeMetadata::new_logged_type(
390 handler,
391 ctx.engines,
392 logged_type_id,
393 ctx.program_name.clone(),
394 )?);
395
396 res.append(&mut exp.collect_types_metadata(handler, ctx)?)
399 }
400 Ref(exp) | Deref(exp) => res.append(&mut exp.collect_types_metadata(handler, ctx)?),
401 VariableExpression { .. }
405 | ConstantExpression { .. }
406 | ConfigurableExpression { .. }
407 | ConstGenericExpression { .. }
408 | StorageAccess { .. }
409 | Literal(_)
410 | AbiName(_)
411 | Break
412 | Continue
413 | FunctionParameter => {}
414 Reassignment(reassignment) => {
415 res.append(&mut reassignment.rhs.collect_types_metadata(handler, ctx)?);
416 }
417 }
418 Ok(res)
419 }
420}
421
422impl MaterializeConstGenerics for TyExpression {
423 fn materialize_const_generics(
424 &mut self,
425 engines: &Engines,
426 handler: &Handler,
427 name: &str,
428 value: &TyExpression,
429 ) -> Result<HasChanges, ErrorEmitted> {
430 let mut has_changes = self
431 .return_type
432 .materialize_const_generics(engines, handler, name, value)?;
433 has_changes |= match &mut self.expression {
434 TyExpressionVariant::CodeBlock(block) => {
435 let mut has_changes = HasChanges::No;
436 for node in block.contents.iter_mut() {
437 has_changes |=
438 node.materialize_const_generics(engines, handler, name, value)?;
439 }
440 Ok(has_changes)
441 }
442 TyExpressionVariant::ConstGenericExpression { decl, .. } => {
443 decl.materialize_const_generics(engines, handler, name, value)
444 }
445 TyExpressionVariant::ImplicitReturn(expr) => {
446 expr.materialize_const_generics(engines, handler, name, value)
447 }
448 TyExpressionVariant::FunctionApplication {
449 arguments,
450 type_binding,
451 fn_ref,
452 ..
453 } => {
454 let mut has_changes = HasChanges::No;
455
456 let fn_decl = engines.de().get(fn_ref.id());
458 if !fn_decl.is_trait_method_dummy {
459 let mut type_subst_map = TypeSubstMap::new();
460 type_subst_map
461 .const_generics_materialization
462 .insert(name.to_string(), value.clone());
463
464 let mut new_decl = TyFunctionDecl::clone(&*fn_decl);
465 if new_decl
466 .subst_inner(&SubstTypesContext {
467 handler,
468 engines,
469 type_subst_map: Some(&type_subst_map),
470 subst_function_body: true,
471 })
472 .has_changes()
473 {
474 *fn_ref = engines.de().insert_modified(new_decl, *fn_ref.id());
475 has_changes = HasChanges::Yes;
476 }
477 }
478
479 if let Some(type_binding) = type_binding.as_mut() {
480 has_changes |= type_binding
481 .type_arguments
482 .to_vec_mut()
483 .materialize_const_generics(engines, handler, name, value)?;
484 }
485
486 for (_, expr) in arguments {
487 has_changes |=
488 expr.materialize_const_generics(engines, handler, name, value)?;
489 }
490 Ok(has_changes)
491 }
492 TyExpressionVariant::IntrinsicFunction(TyIntrinsicFunctionKind {
493 arguments,
494 type_arguments,
495 ..
496 }) => {
497 let has_changes = has_changes! {
498 type_arguments.materialize_const_generics(engines, handler, name, value)?;
499 arguments.materialize_const_generics(engines, handler, name, value)?;
500 };
501 Ok(has_changes)
502 }
503 TyExpressionVariant::Return(expr) => {
504 expr.materialize_const_generics(engines, handler, name, value)
505 }
506 TyExpressionVariant::IfExp {
507 condition,
508 then,
509 r#else,
510 } => {
511 let mut has_changes = has_changes! {
512 condition.materialize_const_generics(engines, handler, name, value)?;
513 then.materialize_const_generics(engines, handler, name, value)?;
514 };
515 if let Some(e) = r#else.as_mut() {
516 has_changes |= e.materialize_const_generics(engines, handler, name, value)?;
517 }
518 Ok(has_changes)
519 }
520 TyExpressionVariant::WhileLoop { condition, body } => {
521 let has_changes = has_changes! {
522 condition.materialize_const_generics(engines, handler, name, value)?;
523 body.materialize_const_generics(engines, handler, name, value)?;
524 };
525 Ok(has_changes)
526 }
527 TyExpressionVariant::Reassignment(expr) => expr
528 .rhs
529 .materialize_const_generics(engines, handler, name, value),
530 TyExpressionVariant::ArrayIndex { prefix, index } => {
531 let has_changes = has_changes! {
532 prefix.materialize_const_generics(engines, handler, name, value)?;
533 index.materialize_const_generics(engines, handler, name, value)?;
534 };
535 Ok(has_changes)
536 }
537 TyExpressionVariant::Literal(_) | TyExpressionVariant::VariableExpression { .. } => {
538 Ok(HasChanges::No)
539 }
540 TyExpressionVariant::ArrayExplicit {
541 elem_type,
542 contents,
543 } => {
544 let mut has_changes =
545 elem_type.materialize_const_generics(engines, handler, name, value)?;
546 for item in contents.iter_mut() {
547 has_changes |=
548 item.materialize_const_generics(engines, handler, name, value)?;
549 }
550 Ok(has_changes)
551 }
552 TyExpressionVariant::ArrayRepeat {
553 elem_type,
554 value: elem_value,
555 length,
556 } => {
557 let has_changes = has_changes! {
558 elem_type.materialize_const_generics(engines, handler, name, value)?;
559 elem_value.materialize_const_generics(engines, handler, name, value)?;
560 length.materialize_const_generics(engines, handler, name, value)?;
561 };
562 Ok(has_changes)
563 }
564 TyExpressionVariant::Ref(r) => {
565 r.materialize_const_generics(engines, handler, name, value)
566 }
567 TyExpressionVariant::Deref(r) => {
568 r.materialize_const_generics(engines, handler, name, value)
569 }
570 TyExpressionVariant::MatchExp { desugared, .. } => {
571 desugared.materialize_const_generics(engines, handler, name, value)
572 }
573 TyExpressionVariant::EnumInstantiation { contents, .. } => {
574 let mut has_changes = HasChanges::No;
575 if let Some(contents) = contents.as_mut() {
576 has_changes |=
577 contents.materialize_const_generics(engines, handler, name, value)?;
578 }
579 Ok(has_changes)
580 }
581 TyExpressionVariant::EnumTag { exp } => {
582 exp.materialize_const_generics(engines, handler, name, value)
583 }
584 TyExpressionVariant::Tuple { fields } => {
585 let mut has_changes = HasChanges::No;
586 for f in fields {
587 has_changes |= f.materialize_const_generics(engines, handler, name, value)?;
588 }
589 Ok(has_changes)
590 }
591 TyExpressionVariant::TupleElemAccess {
592 prefix,
593 resolved_type_of_parent,
594 ..
595 } => {
596 let has_changes = has_changes! {
597 prefix.materialize_const_generics(engines, handler, name, value)?;
598 resolved_type_of_parent.materialize_const_generics(engines, handler, name, value)?;
599 };
600 Ok(has_changes)
601 }
602 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
603 let has_changes = has_changes! {
604 lhs.materialize_const_generics(engines, handler, name, value)?;
605 rhs.materialize_const_generics(engines, handler, name, value)?;
606 };
607 Ok(has_changes)
608 }
609 TyExpressionVariant::AsmExpression { registers, .. } => {
610 let mut has_changes = HasChanges::No;
611 for r in registers.iter_mut() {
612 if let Some(init) = r.initializer.as_mut() {
613 has_changes |=
614 init.materialize_const_generics(engines, handler, name, value)?;
615 }
616 }
617 Ok(has_changes)
618 }
619 TyExpressionVariant::ConstantExpression { decl, .. } => {
620 decl.materialize_const_generics(engines, handler, name, value)
621 }
622 TyExpressionVariant::StructExpression { fields, .. } => {
623 let mut has_changes = HasChanges::No;
624 for f in fields {
625 has_changes |= f
626 .value
627 .materialize_const_generics(engines, handler, name, value)?;
628 }
629 Ok(has_changes)
630 }
631 TyExpressionVariant::StructFieldAccess {
632 prefix,
633 resolved_type_of_parent,
634 ..
635 } => {
636 let has_changes = has_changes! {
637 prefix.materialize_const_generics(engines, handler, name, value)?;
638 resolved_type_of_parent
639 .materialize_const_generics(engines, handler, name, value)?;
640 };
641 Ok(has_changes)
642 }
643 TyExpressionVariant::UnsafeDowncast { exp, .. } => {
644 exp.materialize_const_generics(engines, handler, name, value)
645 }
646 TyExpressionVariant::Continue | TyExpressionVariant::Break => Ok(HasChanges::No),
647 TyExpressionVariant::AbiCast { address, .. } => {
648 address.materialize_const_generics(engines, handler, name, value)
649 }
650 _ => Err(handler.emit_err(
651 sway_error::error::CompileError::ConstGenericNotSupportedHere {
652 span: self.span.clone(),
653 },
654 )),
655 }?;
656 Ok(has_changes)
657 }
658}
659
660impl TyExpression {
661 pub(crate) fn u64_literal(value: u64, span: Span, engines: &Engines) -> TyExpression {
662 let type_engine = engines.te();
663 TyExpression {
664 expression: TyExpressionVariant::Literal(Literal::U64(value)),
665 return_type: type_engine.id_of_u64(),
666 span,
667 }
668 }
669
670 pub(crate) fn error(err: ErrorEmitted, span: Span, engines: &Engines) -> TyExpression {
671 let type_engine = engines.te();
672 TyExpression {
673 expression: TyExpressionVariant::Tuple { fields: vec![] },
674 return_type: type_engine.id_of_error_recovery(err),
675 span,
676 }
677 }
678
679 pub(crate) fn gather_mutability(&self) -> VariableMutability {
681 match &self.expression {
682 TyExpressionVariant::VariableExpression { mutability, .. } => *mutability,
683 _ => VariableMutability::Immutable,
684 }
685 }
686
687 pub(crate) fn extract_literal_value(&self) -> Option<Literal> {
689 self.expression.extract_literal_value()
690 }
691
692 pub(crate) fn check_deprecated(
696 &self,
697 engines: &Engines,
698 handler: &Handler,
699 allow_deprecated: &mut AllowDeprecatedState,
700 ) {
701 fn emit_warning_if_deprecated(
702 attributes: &Attributes,
703 span: &Span,
704 handler: &Handler,
705 deprecated_element: DeprecatedElement,
706 deprecated_element_name: &str,
707 allow_deprecated: &mut AllowDeprecatedState,
708 ) {
709 if allow_deprecated.is_allowed() {
710 return;
711 }
712
713 let Some(deprecated_attr) = attributes.deprecated() else {
714 return;
715 };
716
717 let help = deprecated_attr
718 .args
719 .iter()
720 .rfind(|arg| arg.is_deprecated_note())
722 .and_then(|note_arg| match note_arg.get_string_opt(handler) {
723 Ok(note) => note.cloned(),
724 Err(_) => None,
727 });
728
729 handler.emit_warn(CompileWarning {
730 span: span.clone(),
731 warning_content: Warning::UsingDeprecated {
732 deprecated_element,
733 deprecated_element_name: deprecated_element_name.to_string(),
734 help,
735 },
736 })
737 }
738
739 match &self.expression {
740 TyExpressionVariant::Literal(..) => {}
741 TyExpressionVariant::FunctionApplication {
742 call_path,
743 fn_ref,
744 arguments,
745 ..
746 } => {
747 for (_, expr) in arguments {
748 expr.check_deprecated(engines, handler, allow_deprecated);
749 }
750
751 let fn_ty = engines.de().get(fn_ref);
752 if let Some(TyDecl::ImplSelfOrTrait(t)) = &fn_ty.implementing_type {
753 let t = &engines.de().get(&t.decl_id).implementing_for;
754 if let TypeInfo::Struct(struct_id) = &*engines.te().get(t.type_id) {
755 let s = engines.de().get(struct_id);
756 emit_warning_if_deprecated(
757 &s.attributes,
758 &call_path.span(),
759 handler,
760 DeprecatedElement::Struct,
761 s.call_path.suffix.as_str(),
762 allow_deprecated,
763 );
764 }
765 }
766
767 emit_warning_if_deprecated(
768 &fn_ty.attributes,
769 &call_path.span(),
770 handler,
771 DeprecatedElement::Function,
772 fn_ty.call_path.suffix.as_str(),
773 allow_deprecated,
774 );
775 }
776 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
777 lhs.check_deprecated(engines, handler, allow_deprecated);
778 rhs.check_deprecated(engines, handler, allow_deprecated);
779 }
780 TyExpressionVariant::ConstantExpression { span, decl, .. } => {
781 emit_warning_if_deprecated(
782 &decl.attributes,
783 span,
784 handler,
785 DeprecatedElement::Const,
786 decl.call_path.suffix.as_str(),
787 allow_deprecated,
788 );
789 }
790 TyExpressionVariant::ConfigurableExpression { span, decl, .. } => {
791 emit_warning_if_deprecated(
792 &decl.attributes,
793 span,
794 handler,
795 DeprecatedElement::Configurable,
796 decl.call_path.suffix.as_str(),
797 allow_deprecated,
798 );
799 }
800 TyExpressionVariant::ConstGenericExpression { .. } => {}
802 TyExpressionVariant::VariableExpression { .. } => {}
803 TyExpressionVariant::Tuple { fields } => {
804 for e in fields {
805 e.check_deprecated(engines, handler, allow_deprecated);
806 }
807 }
808 TyExpressionVariant::ArrayExplicit { contents, .. } => {
809 for e in contents {
810 e.check_deprecated(engines, handler, allow_deprecated);
811 }
812 }
813 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
814 value.check_deprecated(engines, handler, allow_deprecated);
815 length.check_deprecated(engines, handler, allow_deprecated);
816 }
817 TyExpressionVariant::ArrayIndex { prefix, index } => {
818 prefix.check_deprecated(engines, handler, allow_deprecated);
819 index.check_deprecated(engines, handler, allow_deprecated);
820 }
821 TyExpressionVariant::StructExpression {
822 struct_id,
823 instantiation_span,
824 ..
825 } => {
826 let struct_decl = engines.de().get(struct_id);
827 emit_warning_if_deprecated(
828 &struct_decl.attributes,
829 instantiation_span,
830 handler,
831 DeprecatedElement::Struct,
832 struct_decl.call_path.suffix.as_str(),
833 allow_deprecated,
834 );
835 }
836 TyExpressionVariant::CodeBlock(block) => {
837 block.check_deprecated(engines, handler, allow_deprecated);
838 }
839 TyExpressionVariant::FunctionParameter => {}
840 TyExpressionVariant::MatchExp {
841 desugared,
842 ..
845 } => {
846 desugared.check_deprecated(engines, handler, allow_deprecated);
847 }
848 TyExpressionVariant::IfExp {
849 condition,
850 then,
851 r#else,
852 } => {
853 condition.check_deprecated(engines, handler, allow_deprecated);
854 then.check_deprecated(engines, handler, allow_deprecated);
855 if let Some(e) = r#else {
856 e.check_deprecated(engines, handler, allow_deprecated);
857 }
858 }
859 TyExpressionVariant::AsmExpression { .. } => {}
860 TyExpressionVariant::StructFieldAccess {
861 prefix,
862 field_to_access,
863 field_instantiation_span,
864 ..
865 } => {
866 prefix.check_deprecated(engines, handler, allow_deprecated);
867 emit_warning_if_deprecated(
868 &field_to_access.attributes,
869 field_instantiation_span,
870 handler,
871 DeprecatedElement::StructField,
872 field_to_access.name.as_str(),
873 allow_deprecated,
874 );
875 }
876 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
877 prefix.check_deprecated(engines, handler, allow_deprecated);
878 }
879 TyExpressionVariant::EnumInstantiation {
880 enum_ref,
881 tag,
882 contents,
883 variant_instantiation_span,
884 call_path_binding,
885 ..
886 } => {
887 let enum_ty = engines.de().get(enum_ref);
888 emit_warning_if_deprecated(
889 &enum_ty.attributes,
890 &call_path_binding.span,
892 handler,
893 DeprecatedElement::Enum,
894 enum_ty.call_path.suffix.as_str(),
895 allow_deprecated,
896 );
897 if let Some(variant_decl) = enum_ty.variants.get(*tag) {
898 emit_warning_if_deprecated(
899 &variant_decl.attributes,
900 variant_instantiation_span,
901 handler,
902 DeprecatedElement::EnumVariant,
903 variant_decl.name.as_str(),
904 allow_deprecated,
905 );
906 }
907 if let Some(expr) = contents {
908 expr.check_deprecated(engines, handler, allow_deprecated);
909 }
910 }
911 TyExpressionVariant::AbiCast { address, .. } => {
912 address.check_deprecated(engines, handler, allow_deprecated);
915 }
916 TyExpressionVariant::StorageAccess(access) => {
917 if let Some(expr) = &access.key_expression {
920 expr.check_deprecated(engines, handler, allow_deprecated);
921 }
922 }
923 TyExpressionVariant::IntrinsicFunction(kind) => {
924 for arg in kind.arguments.iter() {
925 arg.check_deprecated(engines, handler, allow_deprecated);
926 }
927 }
928 TyExpressionVariant::AbiName(..) => {}
929 TyExpressionVariant::EnumTag { exp } => {
930 exp.check_deprecated(engines, handler, allow_deprecated);
931 }
932 TyExpressionVariant::UnsafeDowncast {
933 exp,
934 ..
937 } => {
938 exp.check_deprecated(engines, handler, allow_deprecated);
939 }
940 TyExpressionVariant::WhileLoop { condition, body } => {
941 condition.check_deprecated(engines, handler, allow_deprecated);
942 body.check_deprecated(engines, handler, allow_deprecated);
943 }
944 TyExpressionVariant::ForLoop { desugared } => {
945 desugared.check_deprecated(engines, handler, allow_deprecated);
946 }
947 TyExpressionVariant::Break => {}
948 TyExpressionVariant::Continue => {}
949 TyExpressionVariant::Reassignment(reass) => {
950 if let TyReassignmentTarget::DerefAccess { exp, indices } = &reass.lhs {
951 exp.check_deprecated(engines, handler, allow_deprecated);
952 for indice in indices {
953 match indice {
954 ProjectionKind::StructField {
955 name: idx_name,
956 field_to_access,
957 } => {
958 if let Some(field_to_access) = field_to_access {
959 emit_warning_if_deprecated(
960 &field_to_access.attributes,
961 &idx_name.span(),
962 handler,
963 DeprecatedElement::StructField,
964 idx_name.as_str(),
965 allow_deprecated,
966 );
967 }
968 }
969 ProjectionKind::TupleField {
970 index: _,
971 index_span: _,
972 } => {}
973 ProjectionKind::ArrayIndex {
974 index,
975 index_span: _,
976 } => index.check_deprecated(engines, handler, allow_deprecated),
977 }
978 }
979 }
980 reass
983 .rhs
984 .check_deprecated(engines, handler, allow_deprecated);
985 }
986 TyExpressionVariant::ImplicitReturn(expr) => {
987 expr.check_deprecated(engines, handler, allow_deprecated);
988 }
989 TyExpressionVariant::Return(expr) => {
990 expr.check_deprecated(engines, handler, allow_deprecated);
991 }
992 TyExpressionVariant::Panic(expr) => {
993 expr.check_deprecated(engines, handler, allow_deprecated);
994 }
995 TyExpressionVariant::Ref(expr) => {
996 expr.check_deprecated(engines, handler, allow_deprecated);
997 }
998 TyExpressionVariant::Deref(expr) => {
999 expr.check_deprecated(engines, handler, allow_deprecated);
1000 }
1001 }
1002 }
1003
1004 pub fn as_array(&self) -> Option<(&TypeId, &[TyExpression])> {
1005 match &self.expression {
1006 TyExpressionVariant::ArrayExplicit {
1007 elem_type,
1008 contents,
1009 } => Some((elem_type, contents)),
1010 _ => None,
1011 }
1012 }
1013
1014 pub fn as_intrinsic(&self) -> Option<&TyIntrinsicFunctionKind> {
1015 match &self.expression {
1016 TyExpressionVariant::IntrinsicFunction(v) => Some(v),
1017 _ => None,
1018 }
1019 }
1020
1021 pub fn as_array_unify_elements(&self, handler: &Handler, engines: &Engines) {
1024 let TyExpressionVariant::ArrayExplicit {
1025 elem_type,
1026 contents,
1027 } = &self.expression
1028 else {
1029 unreachable!("Should only be called on Arrays")
1030 };
1031
1032 let array_elem_type = engines.te().get(*elem_type);
1033 if !matches!(&*array_elem_type, TypeInfo::Never) {
1034 let unify = crate::type_system::unify::unifier::Unifier::new(
1035 engines,
1036 "",
1037 unify::unifier::UnifyKind::Default,
1038 );
1039 for element in contents {
1040 let element_type = engines.te().get(element.return_type);
1041
1042 if matches!(&*element_type, TypeInfo::Never) {
1044 continue;
1045 }
1046
1047 let h = Handler::default();
1048 unify.unify(&h, element.return_type, *elem_type, &element.span, true);
1049
1050 if h.has_errors() {
1053 handler.emit_err(CompileError::TypeError(TypeError::MismatchedType {
1054 expected: engines.help_out(&*array_elem_type).to_string(),
1055 received: engines.help_out(&*element_type).to_string(),
1056 help_text: String::new(),
1057 span: element.span.clone(),
1058 }));
1059 }
1060 }
1061 }
1062 }
1063}