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 engines,
455 type_subst_map: Some(&type_subst_map),
456 subst_function_body: true,
457 });
458
459 if matches!(r, HasChanges::Yes) {
460 *fn_ref = engines.de().insert(new_decl, None);
461 }
462 }
463
464 if let Some(type_binding) = type_binding.as_mut() {
465 type_binding
466 .type_arguments
467 .to_vec_mut()
468 .materialize_const_generics(engines, handler, name, value)?;
469 }
470
471 for (_, expr) in arguments {
472 expr.materialize_const_generics(engines, handler, name, value)?;
473 }
474 Ok(())
475 }
476 TyExpressionVariant::IntrinsicFunction(TyIntrinsicFunctionKind {
477 arguments,
478 type_arguments,
479 ..
480 }) => {
481 type_arguments.materialize_const_generics(engines, handler, name, value)?;
482 arguments.materialize_const_generics(engines, handler, name, value)
483 }
484 TyExpressionVariant::Return(expr) => {
485 expr.materialize_const_generics(engines, handler, name, value)
486 }
487 TyExpressionVariant::IfExp {
488 condition,
489 then,
490 r#else,
491 } => {
492 condition.materialize_const_generics(engines, handler, name, value)?;
493 then.materialize_const_generics(engines, handler, name, value)?;
494 if let Some(e) = r#else.as_mut() {
495 e.materialize_const_generics(engines, handler, name, value)?;
496 }
497 Ok(())
498 }
499 TyExpressionVariant::WhileLoop { condition, body } => {
500 condition.materialize_const_generics(engines, handler, name, value)?;
501 body.materialize_const_generics(engines, handler, name, value)
502 }
503 TyExpressionVariant::Reassignment(expr) => expr
504 .rhs
505 .materialize_const_generics(engines, handler, name, value),
506 TyExpressionVariant::ArrayIndex { prefix, index } => {
507 prefix.materialize_const_generics(engines, handler, name, value)?;
508 index.materialize_const_generics(engines, handler, name, value)
509 }
510 TyExpressionVariant::Literal(_) | TyExpressionVariant::VariableExpression { .. } => {
511 Ok(())
512 }
513 TyExpressionVariant::ArrayExplicit {
514 elem_type,
515 contents,
516 } => {
517 elem_type.materialize_const_generics(engines, handler, name, value)?;
518 for item in contents.iter_mut() {
519 item.materialize_const_generics(engines, handler, name, value)?;
520 }
521 Ok(())
522 }
523 TyExpressionVariant::ArrayRepeat {
524 elem_type,
525 value: elem_value,
526 length,
527 } => {
528 elem_type.materialize_const_generics(engines, handler, name, value)?;
529 elem_value.materialize_const_generics(engines, handler, name, value)?;
530 length.materialize_const_generics(engines, handler, name, value)
531 }
532 TyExpressionVariant::Ref(r) => {
533 r.materialize_const_generics(engines, handler, name, value)
534 }
535 TyExpressionVariant::Deref(r) => {
536 r.materialize_const_generics(engines, handler, name, value)
537 }
538 TyExpressionVariant::MatchExp { desugared, .. } => {
539 desugared.materialize_const_generics(engines, handler, name, value)
540 }
541 TyExpressionVariant::EnumInstantiation { contents, .. } => {
542 if let Some(contents) = contents.as_mut() {
543 contents.materialize_const_generics(engines, handler, name, value)?;
544 }
545 Ok(())
546 }
547 TyExpressionVariant::EnumTag { exp } => {
548 exp.materialize_const_generics(engines, handler, name, value)
549 }
550 TyExpressionVariant::Tuple { fields } => {
551 for f in fields {
552 f.materialize_const_generics(engines, handler, name, value)?;
553 }
554 Ok(())
555 }
556 TyExpressionVariant::TupleElemAccess {
557 prefix,
558 resolved_type_of_parent,
559 ..
560 } => {
561 prefix.materialize_const_generics(engines, handler, name, value)?;
562 resolved_type_of_parent
563 .materialize_const_generics(engines, handler, name, value)?;
564 Ok(())
565 }
566 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
567 lhs.materialize_const_generics(engines, handler, name, value)?;
568 rhs.materialize_const_generics(engines, handler, name, value)
569 }
570 TyExpressionVariant::AsmExpression { registers, .. } => {
571 for r in registers.iter_mut() {
572 if let Some(init) = r.initializer.as_mut() {
573 init.materialize_const_generics(engines, handler, name, value)?;
574 }
575 }
576 Ok(())
577 }
578 TyExpressionVariant::ConstantExpression { decl, .. } => {
579 decl.materialize_const_generics(engines, handler, name, value)
580 }
581 TyExpressionVariant::StructExpression { fields, .. } => {
582 for f in fields {
583 f.value
584 .materialize_const_generics(engines, handler, name, value)?;
585 }
586 Ok(())
587 }
588 TyExpressionVariant::StructFieldAccess {
589 prefix,
590 resolved_type_of_parent,
591 ..
592 } => {
593 prefix.materialize_const_generics(engines, handler, name, value)?;
594 resolved_type_of_parent.materialize_const_generics(engines, handler, name, value)
595 }
596 TyExpressionVariant::UnsafeDowncast { exp, .. } => {
597 exp.materialize_const_generics(engines, handler, name, value)
598 }
599 TyExpressionVariant::Continue | TyExpressionVariant::Break => Ok(()),
600 TyExpressionVariant::AbiCast { address, .. } => {
601 address.materialize_const_generics(engines, handler, name, value)
602 }
603 _ => Err(handler.emit_err(
604 sway_error::error::CompileError::ConstGenericNotSupportedHere {
605 span: self.span.clone(),
606 },
607 )),
608 }
609 }
610}
611
612impl TyExpression {
613 pub(crate) fn error(err: ErrorEmitted, span: Span, engines: &Engines) -> TyExpression {
614 let type_engine = engines.te();
615 TyExpression {
616 expression: TyExpressionVariant::Tuple { fields: vec![] },
617 return_type: type_engine.id_of_error_recovery(err),
618 span,
619 }
620 }
621
622 pub(crate) fn gather_mutability(&self) -> VariableMutability {
624 match &self.expression {
625 TyExpressionVariant::VariableExpression { mutability, .. } => *mutability,
626 _ => VariableMutability::Immutable,
627 }
628 }
629
630 pub(crate) fn extract_literal_value(&self) -> Option<Literal> {
632 self.expression.extract_literal_value()
633 }
634
635 pub(crate) fn check_deprecated(
639 &self,
640 engines: &Engines,
641 handler: &Handler,
642 allow_deprecated: &mut AllowDeprecatedState,
643 ) {
644 fn emit_warning_if_deprecated(
645 attributes: &Attributes,
646 span: &Span,
647 handler: &Handler,
648 deprecated_element: DeprecatedElement,
649 deprecated_element_name: &str,
650 allow_deprecated: &mut AllowDeprecatedState,
651 ) {
652 if allow_deprecated.is_allowed() {
653 return;
654 }
655
656 let Some(deprecated_attr) = attributes.deprecated() else {
657 return;
658 };
659
660 let help = deprecated_attr
661 .args
662 .iter()
663 .rfind(|arg| arg.is_deprecated_note())
665 .and_then(|note_arg| match note_arg.get_string_opt(handler) {
666 Ok(note) => note.cloned(),
667 Err(_) => None,
670 });
671
672 handler.emit_warn(CompileWarning {
673 span: span.clone(),
674 warning_content: Warning::UsingDeprecated {
675 deprecated_element,
676 deprecated_element_name: deprecated_element_name.to_string(),
677 help,
678 },
679 })
680 }
681
682 match &self.expression {
683 TyExpressionVariant::Literal(..) => {}
684 TyExpressionVariant::FunctionApplication {
685 call_path,
686 fn_ref,
687 arguments,
688 ..
689 } => {
690 for (_, expr) in arguments {
691 expr.check_deprecated(engines, handler, allow_deprecated);
692 }
693
694 let fn_ty = engines.de().get(fn_ref);
695 if let Some(TyDecl::ImplSelfOrTrait(t)) = &fn_ty.implementing_type {
696 let t = &engines.de().get(&t.decl_id).implementing_for;
697 if let TypeInfo::Struct(struct_id) = &*engines.te().get(t.type_id()) {
698 let s = engines.de().get(struct_id);
699 emit_warning_if_deprecated(
700 &s.attributes,
701 &call_path.span(),
702 handler,
703 DeprecatedElement::Struct,
704 s.call_path.suffix.as_str(),
705 allow_deprecated,
706 );
707 }
708 }
709
710 emit_warning_if_deprecated(
711 &fn_ty.attributes,
712 &call_path.span(),
713 handler,
714 DeprecatedElement::Function,
715 fn_ty.call_path.suffix.as_str(),
716 allow_deprecated,
717 );
718 }
719 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
720 lhs.check_deprecated(engines, handler, allow_deprecated);
721 rhs.check_deprecated(engines, handler, allow_deprecated);
722 }
723 TyExpressionVariant::ConstantExpression { span, decl, .. } => {
724 emit_warning_if_deprecated(
725 &decl.attributes,
726 span,
727 handler,
728 DeprecatedElement::Const,
729 decl.call_path.suffix.as_str(),
730 allow_deprecated,
731 );
732 }
733 TyExpressionVariant::ConfigurableExpression { span, decl, .. } => {
734 emit_warning_if_deprecated(
735 &decl.attributes,
736 span,
737 handler,
738 DeprecatedElement::Configurable,
739 decl.call_path.suffix.as_str(),
740 allow_deprecated,
741 );
742 }
743 TyExpressionVariant::ConstGenericExpression { .. } => {}
745 TyExpressionVariant::VariableExpression { .. } => {}
746 TyExpressionVariant::Tuple { fields } => {
747 for e in fields {
748 e.check_deprecated(engines, handler, allow_deprecated);
749 }
750 }
751 TyExpressionVariant::ArrayExplicit { contents, .. } => {
752 for e in contents {
753 e.check_deprecated(engines, handler, allow_deprecated);
754 }
755 }
756 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
757 value.check_deprecated(engines, handler, allow_deprecated);
758 length.check_deprecated(engines, handler, allow_deprecated);
759 }
760 TyExpressionVariant::ArrayIndex { prefix, index } => {
761 prefix.check_deprecated(engines, handler, allow_deprecated);
762 index.check_deprecated(engines, handler, allow_deprecated);
763 }
764 TyExpressionVariant::StructExpression {
765 struct_id,
766 instantiation_span,
767 ..
768 } => {
769 let struct_decl = engines.de().get(struct_id);
770 emit_warning_if_deprecated(
771 &struct_decl.attributes,
772 instantiation_span,
773 handler,
774 DeprecatedElement::Struct,
775 struct_decl.call_path.suffix.as_str(),
776 allow_deprecated,
777 );
778 }
779 TyExpressionVariant::CodeBlock(block) => {
780 block.check_deprecated(engines, handler, allow_deprecated);
781 }
782 TyExpressionVariant::FunctionParameter => {}
783 TyExpressionVariant::MatchExp {
784 desugared,
785 ..
788 } => {
789 desugared.check_deprecated(engines, handler, allow_deprecated);
790 }
791 TyExpressionVariant::IfExp {
792 condition,
793 then,
794 r#else,
795 } => {
796 condition.check_deprecated(engines, handler, allow_deprecated);
797 then.check_deprecated(engines, handler, allow_deprecated);
798 if let Some(e) = r#else {
799 e.check_deprecated(engines, handler, allow_deprecated);
800 }
801 }
802 TyExpressionVariant::AsmExpression { .. } => {}
803 TyExpressionVariant::StructFieldAccess {
804 prefix,
805 field_to_access,
806 field_instantiation_span,
807 ..
808 } => {
809 prefix.check_deprecated(engines, handler, allow_deprecated);
810 emit_warning_if_deprecated(
811 &field_to_access.attributes,
812 field_instantiation_span,
813 handler,
814 DeprecatedElement::StructField,
815 field_to_access.name.as_str(),
816 allow_deprecated,
817 );
818 }
819 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
820 prefix.check_deprecated(engines, handler, allow_deprecated);
821 }
822 TyExpressionVariant::EnumInstantiation {
823 enum_ref,
824 tag,
825 contents,
826 variant_instantiation_span,
827 call_path_binding,
828 ..
829 } => {
830 let enum_ty = engines.de().get(enum_ref);
831 emit_warning_if_deprecated(
832 &enum_ty.attributes,
833 &call_path_binding.span,
835 handler,
836 DeprecatedElement::Enum,
837 enum_ty.call_path.suffix.as_str(),
838 allow_deprecated,
839 );
840 if let Some(variant_decl) = enum_ty.variants.get(*tag) {
841 emit_warning_if_deprecated(
842 &variant_decl.attributes,
843 variant_instantiation_span,
844 handler,
845 DeprecatedElement::EnumVariant,
846 variant_decl.name.as_str(),
847 allow_deprecated,
848 );
849 }
850 if let Some(expr) = contents {
851 expr.check_deprecated(engines, handler, allow_deprecated);
852 }
853 }
854 TyExpressionVariant::AbiCast { address, .. } => {
855 address.check_deprecated(engines, handler, allow_deprecated);
858 }
859 TyExpressionVariant::StorageAccess(access) => {
860 if let Some(expr) = &access.key_expression {
863 expr.check_deprecated(engines, handler, allow_deprecated);
864 }
865 }
866 TyExpressionVariant::IntrinsicFunction(kind) => {
867 for arg in kind.arguments.iter() {
868 arg.check_deprecated(engines, handler, allow_deprecated);
869 }
870 }
871 TyExpressionVariant::AbiName(..) => {}
872 TyExpressionVariant::EnumTag { exp } => {
873 exp.check_deprecated(engines, handler, allow_deprecated);
874 }
875 TyExpressionVariant::UnsafeDowncast {
876 exp,
877 ..
880 } => {
881 exp.check_deprecated(engines, handler, allow_deprecated);
882 }
883 TyExpressionVariant::WhileLoop { condition, body } => {
884 condition.check_deprecated(engines, handler, allow_deprecated);
885 body.check_deprecated(engines, handler, allow_deprecated);
886 }
887 TyExpressionVariant::ForLoop { desugared } => {
888 desugared.check_deprecated(engines, handler, allow_deprecated);
889 }
890 TyExpressionVariant::Break => {}
891 TyExpressionVariant::Continue => {}
892 TyExpressionVariant::Reassignment(reass) => {
893 if let TyReassignmentTarget::DerefAccess { exp, indices } = &reass.lhs {
894 exp.check_deprecated(engines, handler, allow_deprecated);
895 for indice in indices {
896 match indice {
897 ProjectionKind::StructField {
898 name: idx_name,
899 field_to_access,
900 } => {
901 if let Some(field_to_access) = field_to_access {
902 emit_warning_if_deprecated(
903 &field_to_access.attributes,
904 &idx_name.span(),
905 handler,
906 DeprecatedElement::StructField,
907 idx_name.as_str(),
908 allow_deprecated,
909 );
910 }
911 }
912 ProjectionKind::TupleField {
913 index: _,
914 index_span: _,
915 } => {}
916 ProjectionKind::ArrayIndex {
917 index,
918 index_span: _,
919 } => index.check_deprecated(engines, handler, allow_deprecated),
920 }
921 }
922 }
923 reass
926 .rhs
927 .check_deprecated(engines, handler, allow_deprecated);
928 }
929 TyExpressionVariant::ImplicitReturn(expr) => {
930 expr.check_deprecated(engines, handler, allow_deprecated);
931 }
932 TyExpressionVariant::Return(expr) => {
933 expr.check_deprecated(engines, handler, allow_deprecated);
934 }
935 TyExpressionVariant::Panic(expr) => {
936 expr.check_deprecated(engines, handler, allow_deprecated);
937 }
938 TyExpressionVariant::Ref(expr) => {
939 expr.check_deprecated(engines, handler, allow_deprecated);
940 }
941 TyExpressionVariant::Deref(expr) => {
942 expr.check_deprecated(engines, handler, allow_deprecated);
943 }
944 }
945 }
946
947 pub fn as_array(&self) -> Option<(&TypeId, &[TyExpression])> {
948 match &self.expression {
949 TyExpressionVariant::ArrayExplicit {
950 elem_type,
951 contents,
952 } => Some((elem_type, contents)),
953 _ => None,
954 }
955 }
956
957 pub fn as_intrinsic(&self) -> Option<&TyIntrinsicFunctionKind> {
958 match &self.expression {
959 TyExpressionVariant::IntrinsicFunction(v) => Some(v),
960 _ => None,
961 }
962 }
963
964 pub fn as_array_unify_elements(&self, handler: &Handler, engines: &Engines) {
967 let TyExpressionVariant::ArrayExplicit {
968 elem_type,
969 contents,
970 } = &self.expression
971 else {
972 unreachable!("Should only be called on Arrays")
973 };
974
975 let array_elem_type = engines.te().get(*elem_type);
976 if !matches!(&*array_elem_type, TypeInfo::Never) {
977 let unify = crate::type_system::unify::unifier::Unifier::new(
978 engines,
979 "",
980 unify::unifier::UnifyKind::Default,
981 );
982 for element in contents {
983 let element_type = engines.te().get(element.return_type);
984
985 if matches!(&*element_type, TypeInfo::Never) {
987 continue;
988 }
989
990 let h = Handler::default();
991 unify.unify(&h, element.return_type, *elem_type, &element.span, true);
992
993 if h.has_errors() {
996 handler.emit_err(CompileError::TypeError(TypeError::MismatchedType {
997 expected: engines.help_out(&*array_elem_type).to_string(),
998 received: engines.help_out(&*element_type).to_string(),
999 help_text: String::new(),
1000 span: element.span.clone(),
1001 }));
1002 }
1003 }
1004 }
1005 }
1006}