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