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.type_parameters {
227 let p = p
228 .as_type_parameter()
229 .expect("only works for type parameters");
230 ctx.call_site_insert(p.type_id, instantiation_span.clone());
231 }
232 if let TypeInfo::Struct(decl_ref) = &*ctx.engines.te().get(self.return_type) {
233 let decl = decl_engine.get_struct(decl_ref);
234 for p in &decl.type_parameters {
235 let p = p
236 .as_type_parameter()
237 .expect("only works for type parameters");
238 ctx.call_site_insert(p.type_id, instantiation_span.clone());
239 }
240 }
241 for field in fields.iter() {
242 res.append(&mut field.value.collect_types_metadata(handler, ctx)?);
243 }
244 }
245 LazyOperator { lhs, rhs, .. } => {
246 res.append(&mut lhs.collect_types_metadata(handler, ctx)?);
247 res.append(&mut rhs.collect_types_metadata(handler, ctx)?);
248 }
249 ArrayExplicit {
250 elem_type: _,
251 contents,
252 } => {
253 for content in contents.iter() {
254 res.append(&mut content.collect_types_metadata(handler, ctx)?);
255 }
256 }
257 ArrayRepeat {
258 elem_type: _,
259 value,
260 length,
261 } => {
262 res.append(&mut value.collect_types_metadata(handler, ctx)?);
263 res.append(&mut length.collect_types_metadata(handler, ctx)?);
264 }
265 ArrayIndex { prefix, index } => {
266 res.append(&mut (**prefix).collect_types_metadata(handler, ctx)?);
267 res.append(&mut (**index).collect_types_metadata(handler, ctx)?);
268 }
269 CodeBlock(block) => {
270 for content in block.contents.iter() {
271 res.append(&mut content.collect_types_metadata(handler, ctx)?);
272 }
273 }
274 MatchExp { desugared, .. } => {
275 res.append(&mut desugared.collect_types_metadata(handler, ctx)?)
276 }
277 IfExp {
278 condition,
279 then,
280 r#else,
281 } => {
282 res.append(&mut condition.collect_types_metadata(handler, ctx)?);
283 res.append(&mut then.collect_types_metadata(handler, ctx)?);
284 if let Some(r#else) = r#else {
285 res.append(&mut r#else.collect_types_metadata(handler, ctx)?);
286 }
287 }
288 StructFieldAccess {
289 prefix,
290 resolved_type_of_parent,
291 ..
292 } => {
293 res.append(&mut prefix.collect_types_metadata(handler, ctx)?);
294 res.append(&mut resolved_type_of_parent.collect_types_metadata(handler, ctx)?);
295 }
296 TupleElemAccess {
297 prefix,
298 resolved_type_of_parent,
299 ..
300 } => {
301 res.append(&mut prefix.collect_types_metadata(handler, ctx)?);
302 res.append(&mut resolved_type_of_parent.collect_types_metadata(handler, ctx)?);
303 }
304 EnumInstantiation {
305 enum_ref,
306 contents,
307 call_path_binding,
308 ..
309 } => {
310 let enum_decl = decl_engine.get_enum(enum_ref);
311 for p in enum_decl.type_parameters.iter() {
312 let p = p
313 .as_type_parameter()
314 .expect("only works for type parameters");
315 ctx.call_site_insert(p.type_id, call_path_binding.inner.suffix.span())
316 }
317 if let Some(contents) = contents {
318 res.append(&mut contents.collect_types_metadata(handler, ctx)?);
319 }
320 for variant in enum_decl.variants.iter() {
321 res.append(
322 &mut variant
323 .type_argument
324 .type_id()
325 .collect_types_metadata(handler, ctx)?,
326 );
327 }
328 for p in enum_decl.type_parameters.iter() {
329 let p = p
330 .as_type_parameter()
331 .expect("only works for type parameters");
332 res.append(&mut p.type_id.collect_types_metadata(handler, ctx)?);
333 }
334 }
335 AbiCast { address, .. } => {
336 res.append(&mut address.collect_types_metadata(handler, ctx)?);
337 }
338 IntrinsicFunction(kind) => {
339 res.append(&mut kind.collect_types_metadata(handler, ctx)?);
340 }
341 EnumTag { exp } => {
342 res.append(&mut exp.collect_types_metadata(handler, ctx)?);
343 }
344 UnsafeDowncast {
345 exp,
346 variant,
347 call_path_decl: _,
348 } => {
349 res.append(&mut exp.collect_types_metadata(handler, ctx)?);
350 res.append(
351 &mut variant
352 .type_argument
353 .type_id()
354 .collect_types_metadata(handler, ctx)?,
355 );
356 }
357 WhileLoop { condition, body } => {
358 res.append(&mut condition.collect_types_metadata(handler, ctx)?);
359 for content in body.contents.iter() {
360 res.append(&mut content.collect_types_metadata(handler, ctx)?);
361 }
362 }
363 ForLoop { desugared } => {
364 res.append(&mut desugared.collect_types_metadata(handler, ctx)?);
365 }
366 ImplicitReturn(exp) | Return(exp) => {
367 res.append(&mut exp.collect_types_metadata(handler, ctx)?)
368 }
369 Ref(exp) | Deref(exp) => res.append(&mut exp.collect_types_metadata(handler, ctx)?),
370 VariableExpression { .. }
374 | ConstantExpression { .. }
375 | ConfigurableExpression { .. }
376 | ConstGenericExpression { .. }
377 | StorageAccess { .. }
378 | Literal(_)
379 | AbiName(_)
380 | Break
381 | Continue
382 | FunctionParameter => {}
383 Reassignment(reassignment) => {
384 res.append(&mut reassignment.rhs.collect_types_metadata(handler, ctx)?);
385 }
386 }
387 Ok(res)
388 }
389}
390
391impl MaterializeConstGenerics for TyExpression {
392 fn materialize_const_generics(
393 &mut self,
394 engines: &Engines,
395 handler: &Handler,
396 name: &str,
397 value: &TyExpression,
398 ) -> Result<(), ErrorEmitted> {
399 self.return_type
400 .materialize_const_generics(engines, handler, name, value)?;
401 match &mut self.expression {
402 TyExpressionVariant::CodeBlock(block) => {
403 for node in block.contents.iter_mut() {
404 node.materialize_const_generics(engines, handler, name, value)?;
405 }
406 Ok(())
407 }
408 TyExpressionVariant::ConstGenericExpression { decl, .. } => {
409 decl.materialize_const_generics(engines, handler, name, value)
410 }
411 TyExpressionVariant::ImplicitReturn(expr) => {
412 expr.materialize_const_generics(engines, handler, name, value)
413 }
414 TyExpressionVariant::FunctionApplication { arguments, .. } => {
415 for (_, expr) in arguments {
416 expr.materialize_const_generics(engines, handler, name, value)?;
417 }
418 Ok(())
419 }
420 TyExpressionVariant::IntrinsicFunction(TyIntrinsicFunctionKind {
421 arguments, ..
422 }) => {
423 for expr in arguments {
424 expr.materialize_const_generics(engines, handler, name, value)?;
425 }
426 Ok(())
427 }
428 TyExpressionVariant::Return(expr) => {
429 expr.materialize_const_generics(engines, handler, name, value)
430 }
431 TyExpressionVariant::IfExp {
432 condition,
433 then,
434 r#else,
435 } => {
436 condition.materialize_const_generics(engines, handler, name, value)?;
437 then.materialize_const_generics(engines, handler, name, value)?;
438 if let Some(e) = r#else.as_mut() {
439 e.materialize_const_generics(engines, handler, name, value)?;
440 }
441 Ok(())
442 }
443 TyExpressionVariant::WhileLoop { condition, body } => {
444 condition.materialize_const_generics(engines, handler, name, value)?;
445 body.materialize_const_generics(engines, handler, name, value)
446 }
447 TyExpressionVariant::Reassignment(expr) => expr
448 .rhs
449 .materialize_const_generics(engines, handler, name, value),
450 TyExpressionVariant::ArrayIndex { prefix, index } => {
451 prefix.materialize_const_generics(engines, handler, name, value)?;
452 index.materialize_const_generics(engines, handler, name, value)
453 }
454 TyExpressionVariant::Literal(_) | TyExpressionVariant::VariableExpression { .. } => {
455 Ok(())
456 }
457 TyExpressionVariant::ArrayRepeat {
458 elem_type,
459 value: elem_value,
460 length,
461 } => {
462 elem_type.materialize_const_generics(engines, handler, name, value)?;
463 elem_value.materialize_const_generics(engines, handler, name, value)?;
464 length.materialize_const_generics(engines, handler, name, value)
465 }
466 TyExpressionVariant::Ref(r) => {
467 r.materialize_const_generics(engines, handler, name, value)
468 }
469 TyExpressionVariant::Deref(r) => {
470 r.materialize_const_generics(engines, handler, name, value)
471 }
472 _ => Err(handler.emit_err(
473 sway_error::error::CompileError::ConstGenericNotSupportedHere {
474 span: self.span.clone(),
475 },
476 )),
477 }
478 }
479}
480
481impl TyExpression {
482 pub(crate) fn error(err: ErrorEmitted, span: Span, engines: &Engines) -> TyExpression {
483 let type_engine = engines.te();
484 TyExpression {
485 expression: TyExpressionVariant::Tuple { fields: vec![] },
486 return_type: type_engine.id_of_error_recovery(err),
487 span,
488 }
489 }
490
491 pub(crate) fn gather_mutability(&self) -> VariableMutability {
493 match &self.expression {
494 TyExpressionVariant::VariableExpression { mutability, .. } => *mutability,
495 _ => VariableMutability::Immutable,
496 }
497 }
498
499 pub(crate) fn extract_literal_value(&self) -> Option<Literal> {
501 self.expression.extract_literal_value()
502 }
503
504 pub(crate) fn check_deprecated(
508 &self,
509 engines: &Engines,
510 handler: &Handler,
511 allow_deprecated: &mut AllowDeprecatedState,
512 ) {
513 fn emit_warning_if_deprecated(
514 attributes: &Attributes,
515 span: &Span,
516 handler: &Handler,
517 deprecated_element: DeprecatedElement,
518 deprecated_element_name: &str,
519 allow_deprecated: &mut AllowDeprecatedState,
520 ) {
521 if allow_deprecated.is_allowed() {
522 return;
523 }
524
525 let Some(deprecated_attr) = attributes.deprecated() else {
526 return;
527 };
528
529 let help = deprecated_attr
530 .args
531 .iter()
532 .rfind(|arg| arg.is_deprecated_note())
534 .and_then(|note_arg| match note_arg.get_string_opt(handler) {
535 Ok(note) => note.cloned(),
536 Err(_) => None,
539 });
540
541 handler.emit_warn(CompileWarning {
542 span: span.clone(),
543 warning_content: Warning::UsingDeprecated {
544 deprecated_element,
545 deprecated_element_name: deprecated_element_name.to_string(),
546 help,
547 },
548 })
549 }
550
551 match &self.expression {
552 TyExpressionVariant::Literal(..) => {}
553 TyExpressionVariant::FunctionApplication {
554 call_path,
555 fn_ref,
556 arguments,
557 ..
558 } => {
559 for (_, expr) in arguments {
560 expr.check_deprecated(engines, handler, allow_deprecated);
561 }
562
563 let fn_ty = engines.de().get(fn_ref);
564 if let Some(TyDecl::ImplSelfOrTrait(t)) = &fn_ty.implementing_type {
565 let t = &engines.de().get(&t.decl_id).implementing_for;
566 if let TypeInfo::Struct(struct_id) = &*engines.te().get(t.type_id()) {
567 let s = engines.de().get(struct_id);
568 emit_warning_if_deprecated(
569 &s.attributes,
570 &call_path.span(),
571 handler,
572 DeprecatedElement::Struct,
573 s.call_path.suffix.as_str(),
574 allow_deprecated,
575 );
576 }
577 }
578
579 emit_warning_if_deprecated(
580 &fn_ty.attributes,
581 &call_path.span(),
582 handler,
583 DeprecatedElement::Function,
584 fn_ty.call_path.suffix.as_str(),
585 allow_deprecated,
586 );
587 }
588 TyExpressionVariant::LazyOperator { lhs, rhs, .. } => {
589 lhs.check_deprecated(engines, handler, allow_deprecated);
590 rhs.check_deprecated(engines, handler, allow_deprecated);
591 }
592 TyExpressionVariant::ConstantExpression { span, decl, .. } => {
593 emit_warning_if_deprecated(
594 &decl.attributes,
595 span,
596 handler,
597 DeprecatedElement::Const,
598 decl.call_path.suffix.as_str(),
599 allow_deprecated,
600 );
601 }
602 TyExpressionVariant::ConfigurableExpression { span, decl, .. } => {
603 emit_warning_if_deprecated(
604 &decl.attributes,
605 span,
606 handler,
607 DeprecatedElement::Configurable,
608 decl.call_path.suffix.as_str(),
609 allow_deprecated,
610 );
611 }
612 TyExpressionVariant::ConstGenericExpression { .. } => {}
614 TyExpressionVariant::VariableExpression { .. } => {}
615 TyExpressionVariant::Tuple { fields } => {
616 for e in fields {
617 e.check_deprecated(engines, handler, allow_deprecated);
618 }
619 }
620 TyExpressionVariant::ArrayExplicit { contents, .. } => {
621 for e in contents {
622 e.check_deprecated(engines, handler, allow_deprecated);
623 }
624 }
625 TyExpressionVariant::ArrayRepeat { value, length, .. } => {
626 value.check_deprecated(engines, handler, allow_deprecated);
627 length.check_deprecated(engines, handler, allow_deprecated);
628 }
629 TyExpressionVariant::ArrayIndex { prefix, index } => {
630 prefix.check_deprecated(engines, handler, allow_deprecated);
631 index.check_deprecated(engines, handler, allow_deprecated);
632 }
633 TyExpressionVariant::StructExpression {
634 struct_id,
635 instantiation_span,
636 ..
637 } => {
638 let struct_decl = engines.de().get(struct_id);
639 emit_warning_if_deprecated(
640 &struct_decl.attributes,
641 instantiation_span,
642 handler,
643 DeprecatedElement::Struct,
644 struct_decl.call_path.suffix.as_str(),
645 allow_deprecated,
646 );
647 }
648 TyExpressionVariant::CodeBlock(block) => {
649 block.check_deprecated(engines, handler, allow_deprecated);
650 }
651 TyExpressionVariant::FunctionParameter => {}
652 TyExpressionVariant::MatchExp {
653 desugared,
654 ..
657 } => {
658 desugared.check_deprecated(engines, handler, allow_deprecated);
659 }
660 TyExpressionVariant::IfExp {
661 condition,
662 then,
663 r#else,
664 } => {
665 condition.check_deprecated(engines, handler, allow_deprecated);
666 then.check_deprecated(engines, handler, allow_deprecated);
667 if let Some(e) = r#else {
668 e.check_deprecated(engines, handler, allow_deprecated);
669 }
670 }
671 TyExpressionVariant::AsmExpression { .. } => {}
672 TyExpressionVariant::StructFieldAccess {
673 prefix,
674 field_to_access,
675 field_instantiation_span,
676 ..
677 } => {
678 prefix.check_deprecated(engines, handler, allow_deprecated);
679 emit_warning_if_deprecated(
680 &field_to_access.attributes,
681 field_instantiation_span,
682 handler,
683 DeprecatedElement::StructField,
684 field_to_access.name.as_str(),
685 allow_deprecated,
686 );
687 }
688 TyExpressionVariant::TupleElemAccess { prefix, .. } => {
689 prefix.check_deprecated(engines, handler, allow_deprecated);
690 }
691 TyExpressionVariant::EnumInstantiation {
692 enum_ref,
693 tag,
694 contents,
695 variant_instantiation_span,
696 call_path_binding,
697 ..
698 } => {
699 let enum_ty = engines.de().get(enum_ref);
700 emit_warning_if_deprecated(
701 &enum_ty.attributes,
702 &call_path_binding.span,
704 handler,
705 DeprecatedElement::Enum,
706 enum_ty.call_path.suffix.as_str(),
707 allow_deprecated,
708 );
709 if let Some(variant_decl) = enum_ty.variants.get(*tag) {
710 emit_warning_if_deprecated(
711 &variant_decl.attributes,
712 variant_instantiation_span,
713 handler,
714 DeprecatedElement::EnumVariant,
715 variant_decl.name.as_str(),
716 allow_deprecated,
717 );
718 }
719 if let Some(expr) = contents {
720 expr.check_deprecated(engines, handler, allow_deprecated);
721 }
722 }
723 TyExpressionVariant::AbiCast { address, .. } => {
724 address.check_deprecated(engines, handler, allow_deprecated);
727 }
728 TyExpressionVariant::StorageAccess(access) => {
729 if let Some(expr) = &access.key_expression {
732 expr.check_deprecated(engines, handler, allow_deprecated);
733 }
734 }
735 TyExpressionVariant::IntrinsicFunction(kind) => {
736 for arg in kind.arguments.iter() {
737 arg.check_deprecated(engines, handler, allow_deprecated);
738 }
739 }
740 TyExpressionVariant::AbiName(..) => {}
741 TyExpressionVariant::EnumTag { exp } => {
742 exp.check_deprecated(engines, handler, allow_deprecated);
743 }
744 TyExpressionVariant::UnsafeDowncast {
745 exp,
746 ..
749 } => {
750 exp.check_deprecated(engines, handler, allow_deprecated);
751 }
752 TyExpressionVariant::WhileLoop { condition, body } => {
753 condition.check_deprecated(engines, handler, allow_deprecated);
754 body.check_deprecated(engines, handler, allow_deprecated);
755 }
756 TyExpressionVariant::ForLoop { desugared } => {
757 desugared.check_deprecated(engines, handler, allow_deprecated);
758 }
759 TyExpressionVariant::Break => {}
760 TyExpressionVariant::Continue => {}
761 TyExpressionVariant::Reassignment(reass) => {
762 if let TyReassignmentTarget::DerefAccess { exp, indices } = &reass.lhs {
763 exp.check_deprecated(engines, handler, allow_deprecated);
764 for indice in indices {
765 match indice {
766 ProjectionKind::StructField {
767 name: idx_name,
768 field_to_access,
769 } => {
770 if let Some(field_to_access) = field_to_access {
771 emit_warning_if_deprecated(
772 &field_to_access.attributes,
773 &idx_name.span(),
774 handler,
775 DeprecatedElement::StructField,
776 idx_name.as_str(),
777 allow_deprecated,
778 );
779 }
780 }
781 ProjectionKind::TupleField {
782 index: _,
783 index_span: _,
784 } => {}
785 ProjectionKind::ArrayIndex {
786 index,
787 index_span: _,
788 } => index.check_deprecated(engines, handler, allow_deprecated),
789 }
790 }
791 }
792 reass
795 .rhs
796 .check_deprecated(engines, handler, allow_deprecated);
797 }
798 TyExpressionVariant::ImplicitReturn(expr) => {
799 expr.check_deprecated(engines, handler, allow_deprecated);
800 }
801 TyExpressionVariant::Return(expr) => {
802 expr.check_deprecated(engines, handler, allow_deprecated);
803 }
804 TyExpressionVariant::Ref(expr) => {
805 expr.check_deprecated(engines, handler, allow_deprecated);
806 }
807 TyExpressionVariant::Deref(expr) => {
808 expr.check_deprecated(engines, handler, allow_deprecated);
809 }
810 }
811 }
812
813 pub fn as_array(&self) -> Option<(&TypeId, &[TyExpression])> {
814 match &self.expression {
815 TyExpressionVariant::ArrayExplicit {
816 elem_type,
817 contents,
818 } => Some((elem_type, contents)),
819 _ => None,
820 }
821 }
822
823 pub fn as_intrinsic(&self) -> Option<&TyIntrinsicFunctionKind> {
824 match &self.expression {
825 TyExpressionVariant::IntrinsicFunction(v) => Some(v),
826 _ => None,
827 }
828 }
829
830 pub fn as_array_unify_elements(&self, handler: &Handler, engines: &Engines) {
833 let TyExpressionVariant::ArrayExplicit {
834 elem_type,
835 contents,
836 } = &self.expression
837 else {
838 unreachable!("Should only be called on Arrays")
839 };
840
841 let array_elem_type = engines.te().get(*elem_type);
842 if !matches!(&*array_elem_type, TypeInfo::Never) {
843 let unify = crate::type_system::unify::unifier::Unifier::new(
844 engines,
845 "",
846 unify::unifier::UnifyKind::Default,
847 );
848 for element in contents {
849 let element_type = engines.te().get(element.return_type);
850
851 if matches!(&*element_type, TypeInfo::Never) {
853 continue;
854 }
855
856 let h = Handler::default();
857 unify.unify(&h, element.return_type, *elem_type, &element.span, true);
858
859 if h.has_errors() {
862 handler.emit_err(CompileError::TypeError(TypeError::MismatchedType {
863 expected: format!("{:?}", engines.help_out(&array_elem_type)),
864 received: format!("{:?}", engines.help_out(element_type)),
865 help_text: String::new(),
866 span: element.span.clone(),
867 }));
868 }
869 }
870 }
871 }
872}