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