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 error(err: ErrorEmitted, span: Span, engines: &Engines) -> TyExpression {
615 let type_engine = engines.te();
616 TyExpression {
617 expression: TyExpressionVariant::Tuple { fields: vec![] },
618 return_type: type_engine.id_of_error_recovery(err),
619 span,
620 }
621 }
622
623 pub(crate) fn gather_mutability(&self) -> VariableMutability {
625 match &self.expression {
626 TyExpressionVariant::VariableExpression { mutability, .. } => *mutability,
627 _ => VariableMutability::Immutable,
628 }
629 }
630
631 pub(crate) fn extract_literal_value(&self) -> Option<Literal> {
633 self.expression.extract_literal_value()
634 }
635
636 pub(crate) fn check_deprecated(
640 &self,
641 engines: &Engines,
642 handler: &Handler,
643 allow_deprecated: &mut AllowDeprecatedState,
644 ) {
645 fn emit_warning_if_deprecated(
646 attributes: &Attributes,
647 span: &Span,
648 handler: &Handler,
649 deprecated_element: DeprecatedElement,
650 deprecated_element_name: &str,
651 allow_deprecated: &mut AllowDeprecatedState,
652 ) {
653 if allow_deprecated.is_allowed() {
654 return;
655 }
656
657 let Some(deprecated_attr) = attributes.deprecated() else {
658 return;
659 };
660
661 let help = deprecated_attr
662 .args
663 .iter()
664 .rfind(|arg| arg.is_deprecated_note())
666 .and_then(|note_arg| match note_arg.get_string_opt(handler) {
667 Ok(note) => note.cloned(),
668 Err(_) => None,
671 });
672
673 handler.emit_warn(CompileWarning {
674 span: span.clone(),
675 warning_content: Warning::UsingDeprecated {
676 deprecated_element,
677 deprecated_element_name: deprecated_element_name.to_string(),
678 help,
679 },
680 })
681 }
682
683 match &self.expression {
684 TyExpressionVariant::Literal(..) => {}
685 TyExpressionVariant::FunctionApplication {
686 call_path,
687 fn_ref,
688 arguments,
689 ..
690 } => {
691 for (_, expr) in arguments {
692 expr.check_deprecated(engines, handler, allow_deprecated);
693 }
694
695 let fn_ty = engines.de().get(fn_ref);
696 if let Some(TyDecl::ImplSelfOrTrait(t)) = &fn_ty.implementing_type {
697 let t = &engines.de().get(&t.decl_id).implementing_for;
698 if let TypeInfo::Struct(struct_id) = &*engines.te().get(t.type_id) {
699 let s = engines.de().get(struct_id);
700 emit_warning_if_deprecated(
701 &s.attributes,
702 &call_path.span(),
703 handler,
704 DeprecatedElement::Struct,
705 s.call_path.suffix.as_str(),
706 allow_deprecated,
707 );
708 }
709 }
710
711 emit_warning_if_deprecated(
712 &fn_ty.attributes,
713 &call_path.span(),
714 handler,
715 DeprecatedElement::Function,
716 fn_ty.call_path.suffix.as_str(),
717 allow_deprecated,
718 );
719 }
720 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
721 lhs.check_deprecated(engines, handler, allow_deprecated);
722 rhs.check_deprecated(engines, handler, allow_deprecated);
723 }
724 TyExpressionVariant::ConstantExpression { span, decl, .. } => {
725 emit_warning_if_deprecated(
726 &decl.attributes,
727 span,
728 handler,
729 DeprecatedElement::Const,
730 decl.call_path.suffix.as_str(),
731 allow_deprecated,
732 );
733 }
734 TyExpressionVariant::ConfigurableExpression { span, decl, .. } => {
735 emit_warning_if_deprecated(
736 &decl.attributes,
737 span,
738 handler,
739 DeprecatedElement::Configurable,
740 decl.call_path.suffix.as_str(),
741 allow_deprecated,
742 );
743 }
744 TyExpressionVariant::ConstGenericExpression { .. } => {}
746 TyExpressionVariant::VariableExpression { .. } => {}
747 TyExpressionVariant::Tuple { fields } => {
748 for e in fields {
749 e.check_deprecated(engines, handler, allow_deprecated);
750 }
751 }
752 TyExpressionVariant::ArrayExplicit { contents, .. } => {
753 for e in contents {
754 e.check_deprecated(engines, handler, allow_deprecated);
755 }
756 }
757 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
758 value.check_deprecated(engines, handler, allow_deprecated);
759 length.check_deprecated(engines, handler, allow_deprecated);
760 }
761 TyExpressionVariant::ArrayIndex { prefix, index } => {
762 prefix.check_deprecated(engines, handler, allow_deprecated);
763 index.check_deprecated(engines, handler, allow_deprecated);
764 }
765 TyExpressionVariant::StructExpression {
766 struct_id,
767 instantiation_span,
768 ..
769 } => {
770 let struct_decl = engines.de().get(struct_id);
771 emit_warning_if_deprecated(
772 &struct_decl.attributes,
773 instantiation_span,
774 handler,
775 DeprecatedElement::Struct,
776 struct_decl.call_path.suffix.as_str(),
777 allow_deprecated,
778 );
779 }
780 TyExpressionVariant::CodeBlock(block) => {
781 block.check_deprecated(engines, handler, allow_deprecated);
782 }
783 TyExpressionVariant::FunctionParameter => {}
784 TyExpressionVariant::MatchExp {
785 desugared,
786 ..
789 } => {
790 desugared.check_deprecated(engines, handler, allow_deprecated);
791 }
792 TyExpressionVariant::IfExp {
793 condition,
794 then,
795 r#else,
796 } => {
797 condition.check_deprecated(engines, handler, allow_deprecated);
798 then.check_deprecated(engines, handler, allow_deprecated);
799 if let Some(e) = r#else {
800 e.check_deprecated(engines, handler, allow_deprecated);
801 }
802 }
803 TyExpressionVariant::AsmExpression { .. } => {}
804 TyExpressionVariant::StructFieldAccess {
805 prefix,
806 field_to_access,
807 field_instantiation_span,
808 ..
809 } => {
810 prefix.check_deprecated(engines, handler, allow_deprecated);
811 emit_warning_if_deprecated(
812 &field_to_access.attributes,
813 field_instantiation_span,
814 handler,
815 DeprecatedElement::StructField,
816 field_to_access.name.as_str(),
817 allow_deprecated,
818 );
819 }
820 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
821 prefix.check_deprecated(engines, handler, allow_deprecated);
822 }
823 TyExpressionVariant::EnumInstantiation {
824 enum_ref,
825 tag,
826 contents,
827 variant_instantiation_span,
828 call_path_binding,
829 ..
830 } => {
831 let enum_ty = engines.de().get(enum_ref);
832 emit_warning_if_deprecated(
833 &enum_ty.attributes,
834 &call_path_binding.span,
836 handler,
837 DeprecatedElement::Enum,
838 enum_ty.call_path.suffix.as_str(),
839 allow_deprecated,
840 );
841 if let Some(variant_decl) = enum_ty.variants.get(*tag) {
842 emit_warning_if_deprecated(
843 &variant_decl.attributes,
844 variant_instantiation_span,
845 handler,
846 DeprecatedElement::EnumVariant,
847 variant_decl.name.as_str(),
848 allow_deprecated,
849 );
850 }
851 if let Some(expr) = contents {
852 expr.check_deprecated(engines, handler, allow_deprecated);
853 }
854 }
855 TyExpressionVariant::AbiCast { address, .. } => {
856 address.check_deprecated(engines, handler, allow_deprecated);
859 }
860 TyExpressionVariant::StorageAccess(access) => {
861 if let Some(expr) = &access.key_expression {
864 expr.check_deprecated(engines, handler, allow_deprecated);
865 }
866 }
867 TyExpressionVariant::IntrinsicFunction(kind) => {
868 for arg in kind.arguments.iter() {
869 arg.check_deprecated(engines, handler, allow_deprecated);
870 }
871 }
872 TyExpressionVariant::AbiName(..) => {}
873 TyExpressionVariant::EnumTag { exp } => {
874 exp.check_deprecated(engines, handler, allow_deprecated);
875 }
876 TyExpressionVariant::UnsafeDowncast {
877 exp,
878 ..
881 } => {
882 exp.check_deprecated(engines, handler, allow_deprecated);
883 }
884 TyExpressionVariant::WhileLoop { condition, body } => {
885 condition.check_deprecated(engines, handler, allow_deprecated);
886 body.check_deprecated(engines, handler, allow_deprecated);
887 }
888 TyExpressionVariant::ForLoop { desugared } => {
889 desugared.check_deprecated(engines, handler, allow_deprecated);
890 }
891 TyExpressionVariant::Break => {}
892 TyExpressionVariant::Continue => {}
893 TyExpressionVariant::Reassignment(reass) => {
894 if let TyReassignmentTarget::DerefAccess { exp, indices } = &reass.lhs {
895 exp.check_deprecated(engines, handler, allow_deprecated);
896 for indice in indices {
897 match indice {
898 ProjectionKind::StructField {
899 name: idx_name,
900 field_to_access,
901 } => {
902 if let Some(field_to_access) = field_to_access {
903 emit_warning_if_deprecated(
904 &field_to_access.attributes,
905 &idx_name.span(),
906 handler,
907 DeprecatedElement::StructField,
908 idx_name.as_str(),
909 allow_deprecated,
910 );
911 }
912 }
913 ProjectionKind::TupleField {
914 index: _,
915 index_span: _,
916 } => {}
917 ProjectionKind::ArrayIndex {
918 index,
919 index_span: _,
920 } => index.check_deprecated(engines, handler, allow_deprecated),
921 }
922 }
923 }
924 reass
927 .rhs
928 .check_deprecated(engines, handler, allow_deprecated);
929 }
930 TyExpressionVariant::ImplicitReturn(expr) => {
931 expr.check_deprecated(engines, handler, allow_deprecated);
932 }
933 TyExpressionVariant::Return(expr) => {
934 expr.check_deprecated(engines, handler, allow_deprecated);
935 }
936 TyExpressionVariant::Panic(expr) => {
937 expr.check_deprecated(engines, handler, allow_deprecated);
938 }
939 TyExpressionVariant::Ref(expr) => {
940 expr.check_deprecated(engines, handler, allow_deprecated);
941 }
942 TyExpressionVariant::Deref(expr) => {
943 expr.check_deprecated(engines, handler, allow_deprecated);
944 }
945 }
946 }
947
948 pub fn as_array(&self) -> Option<(&TypeId, &[TyExpression])> {
949 match &self.expression {
950 TyExpressionVariant::ArrayExplicit {
951 elem_type,
952 contents,
953 } => Some((elem_type, contents)),
954 _ => None,
955 }
956 }
957
958 pub fn as_intrinsic(&self) -> Option<&TyIntrinsicFunctionKind> {
959 match &self.expression {
960 TyExpressionVariant::IntrinsicFunction(v) => Some(v),
961 _ => None,
962 }
963 }
964
965 pub fn as_array_unify_elements(&self, handler: &Handler, engines: &Engines) {
968 let TyExpressionVariant::ArrayExplicit {
969 elem_type,
970 contents,
971 } = &self.expression
972 else {
973 unreachable!("Should only be called on Arrays")
974 };
975
976 let array_elem_type = engines.te().get(*elem_type);
977 if !matches!(&*array_elem_type, TypeInfo::Never) {
978 let unify = crate::type_system::unify::unifier::Unifier::new(
979 engines,
980 "",
981 unify::unifier::UnifyKind::Default,
982 );
983 for element in contents {
984 let element_type = engines.te().get(element.return_type);
985
986 if matches!(&*element_type, TypeInfo::Never) {
988 continue;
989 }
990
991 let h = Handler::default();
992 unify.unify(&h, element.return_type, *elem_type, &element.span, true);
993
994 if h.has_errors() {
997 handler.emit_err(CompileError::TypeError(TypeError::MismatchedType {
998 expected: engines.help_out(&*array_elem_type).to_string(),
999 received: engines.help_out(&*element_type).to_string(),
1000 help_text: String::new(),
1001 span: element.span.clone(),
1002 }));
1003 }
1004 }
1005 }
1006 }
1007}