1use crate::{
2 decl_engine::*,
3 engine_threading::*,
4 has_changes,
5 language::{
6 parsed::{self, FunctionDeclaration, FunctionDeclarationKind},
7 ty::*,
8 CallPath, Inline, Purity, Trace, Visibility,
9 },
10 semantic_analysis::TypeCheckContext,
11 transform::{self, AttributeKind},
12 type_system::*,
13 types::*,
14};
15use ast_elements::type_parameter::ConstGenericExpr;
16use monomorphization::MonomorphizeHelper;
17use serde::{Deserialize, Serialize};
18use sha2::{Digest, Sha256};
19use std::{
20 collections::BTreeMap,
21 fmt,
22 hash::{Hash, Hasher},
23};
24use sway_error::handler::{ErrorEmitted, Handler};
25use sway_types::{Ident, Named, Span, Spanned};
26
27#[derive(Clone, Debug, Serialize, Deserialize)]
28pub enum TyFunctionDeclKind {
29 Default,
30 Entry,
31 Main,
32 Test,
33}
34
35#[derive(Clone, Debug, Serialize, Deserialize)]
36pub struct TyFunctionDecl {
37 pub name: Ident,
38 pub body: TyCodeBlock,
39 pub parameters: Vec<TyFunctionParameter>,
40 pub implementing_type: Option<TyDecl>,
41 pub implementing_for_typeid: Option<TypeId>,
42 pub span: Span,
43 pub call_path: CallPath,
44 pub attributes: transform::Attributes,
45 pub type_parameters: Vec<TypeParameter>,
46 pub return_type: GenericArgument,
47 pub visibility: Visibility,
48 pub is_contract_call: bool,
50 pub purity: Purity,
51 pub where_clause: Vec<(Ident, Vec<TraitConstraint>)>,
52 pub is_trait_method_dummy: bool,
53 pub is_type_check_finalized: bool,
54 pub kind: TyFunctionDeclKind,
55}
56
57impl TyDeclParsedType for TyFunctionDecl {
58 type ParsedType = FunctionDeclaration;
59}
60
61impl DebugWithEngines for TyFunctionDecl {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
63 write!(
64 f,
65 "{}{:?}{}({}): {:?} -> {:?}",
66 if self.is_trait_method_dummy {
67 "dummy ".to_string()
68 } else {
69 "".to_string()
70 },
71 self.name,
72 if !self.type_parameters.is_empty() {
73 format!(
74 "<{}>",
75 self.type_parameters
76 .iter()
77 .map(|p| format!("{:?}", engines.help_out(p)))
78 .collect::<Vec<_>>()
79 .join(", ")
80 )
81 } else {
82 "".to_string()
83 },
84 self.parameters
85 .iter()
86 .map(|p| format!(
87 "{}: {:?} -> {:?}",
88 p.name.as_str(),
89 engines.help_out(p.type_argument.initial_type_id()),
90 engines.help_out(p.type_argument.type_id())
91 ))
92 .collect::<Vec<_>>()
93 .join(", "),
94 engines.help_out(self.return_type.initial_type_id()),
95 engines.help_out(self.return_type.type_id()),
96 )
97 }
98}
99
100impl DisplayWithEngines for TyFunctionDecl {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
102 write!(
103 f,
104 "{}{}({}) -> {}",
105 self.name,
106 if !self.type_parameters.is_empty() {
107 format!(
108 "<{}>",
109 self.type_parameters
110 .iter()
111 .map(|p| {
112 let p = p
113 .as_type_parameter()
114 .expect("only works for type parameters");
115 format!("{}", engines.help_out(p.initial_type_id))
116 })
117 .collect::<Vec<_>>()
118 .join(", ")
119 )
120 } else {
121 "".to_string()
122 },
123 self.parameters
124 .iter()
125 .map(|p| format!(
126 "{}: {}",
127 p.name.as_str(),
128 engines.help_out(p.type_argument.initial_type_id())
129 ))
130 .collect::<Vec<_>>()
131 .join(", "),
132 engines.help_out(self.return_type.initial_type_id()),
133 )
134 }
135}
136
137impl MaterializeConstGenerics for TyFunctionDecl {
138 fn materialize_const_generics(
139 &mut self,
140 engines: &Engines,
141 handler: &Handler,
142 name: &str,
143 value: &TyExpression,
144 ) -> Result<(), ErrorEmitted> {
145 for tp in self.type_parameters.iter_mut() {
146 match tp {
147 TypeParameter::Type(p) => p
148 .type_id
149 .materialize_const_generics(engines, handler, name, value)?,
150 TypeParameter::Const(p) if p.name.as_str() == name => match p.expr.as_ref() {
151 Some(v) => {
152 assert!(
153 v.as_literal_val().unwrap() as u64
154 == value
155 .extract_literal_value()
156 .unwrap()
157 .cast_value_to_u64()
158 .unwrap()
159 );
160 }
161 None => {
162 p.expr = Some(ConstGenericExpr::from_ty_expression(handler, value)?);
163 }
164 },
165 _ => {}
166 }
167 }
168
169 for param in self.parameters.iter_mut() {
170 param
171 .type_argument
172 .type_id_mut()
173 .materialize_const_generics(engines, handler, name, value)?;
174 }
175 self.return_type
176 .type_id_mut()
177 .materialize_const_generics(engines, handler, name, value)?;
178 self.body
179 .materialize_const_generics(engines, handler, name, value)
180 }
181}
182
183fn rename_const_generics_on_function(
186 engines: &Engines,
187 impl_self_or_trait: &TyImplSelfOrTrait,
188 function: &mut TyFunctionDecl,
189) {
190 let from = impl_self_or_trait.implementing_for.initial_type_id();
191 let to = impl_self_or_trait.implementing_for.type_id();
192
193 let from = engines.te().get(from);
194 let to = engines.te().get(to);
195
196 match (&*from, &*to) {
197 (
198 TypeInfo::Custom {
199 type_arguments: Some(type_arguments),
200 ..
201 },
202 TypeInfo::Struct(s),
203 ) => {
204 let decl = engines.de().get(s);
205 rename_const_generics_on_function_inner(
206 engines,
207 function,
208 type_arguments,
209 decl.type_parameters(),
210 );
211 }
212 (
213 TypeInfo::Custom {
214 type_arguments: Some(type_arguments),
215 ..
216 },
217 TypeInfo::Enum(s),
218 ) => {
219 let decl = engines.de().get(s);
220 rename_const_generics_on_function_inner(
221 engines,
222 function,
223 type_arguments,
224 decl.type_parameters(),
225 );
226 }
227 _ => (),
228 }
229}
230
231fn rename_const_generics_on_function_inner(
232 engines: &Engines,
233 function: &mut TyFunctionDecl,
234 type_arguments: &[GenericArgument],
235 generic_parameters: &[TypeParameter],
236) {
237 for a in type_arguments.iter().zip(generic_parameters.iter()) {
238 match (a.0, a.1) {
239 (GenericArgument::Type(a), TypeParameter::Const(b)) => {
240 let mut type_subst_map = TypeSubstMap::default();
242 type_subst_map.const_generics_renaming.insert(
243 a.call_path_tree
244 .as_ref()
245 .unwrap()
246 .qualified_call_path
247 .call_path
248 .suffix
249 .clone(),
250 b.name.clone(),
251 );
252 function.subst_inner(&SubstTypesContext {
253 engines,
254 type_subst_map: Some(&type_subst_map),
255 subst_function_body: true,
256 });
257 }
258 (GenericArgument::Const(a), TypeParameter::Const(b)) => {
259 engines
260 .obs()
261 .trace(|| format!("{:?} -> {:?}", a.expr, b.expr));
262 }
263 _ => {}
264 }
265 }
266}
267
268impl DeclRefFunction {
269 pub fn get_method_safe_to_unify(&self, engines: &Engines, type_id: TypeId) -> Self {
274 engines.obs().trace(|| {
275 format!(
276 " before get_method_safe_to_unify: {:?} {:?}",
277 engines.help_out(type_id),
278 engines.help_out(self.id())
279 )
280 });
281
282 let decl_engine = engines.de();
283
284 let original = &*decl_engine.get_function(self);
285 let mut method = original.clone();
286
287 if let Some(method_implementing_for_typeid) = method.implementing_for_typeid {
288 let mut type_id_type_subst_map = TypeSubstMap::new();
289
290 if let Some(TyDecl::ImplSelfOrTrait(t)) = method.implementing_type.clone() {
291 let impl_self_or_trait = &*engines.de().get(&t.decl_id);
292 rename_const_generics_on_function(engines, impl_self_or_trait, &mut method);
293
294 let mut type_id_type_parameters = vec![];
295 let mut const_generic_parameters = BTreeMap::default();
296 type_id.extract_type_parameters(
297 engines,
298 0,
299 &mut type_id_type_parameters,
300 &mut const_generic_parameters,
301 impl_self_or_trait.implementing_for.type_id(),
302 );
303
304 type_id_type_subst_map
305 .const_generics_materialization
306 .append(&mut const_generic_parameters);
307
308 for p in impl_self_or_trait
309 .impl_type_parameters
310 .iter()
311 .filter_map(|x| x.as_type_parameter())
312 {
313 let matches = type_id_type_parameters
314 .iter()
315 .filter(|(_, orig_tp)| {
316 engines.te().get(*orig_tp).eq(
317 &*engines.te().get(p.type_id),
318 &PartialEqWithEnginesContext::new(engines),
319 )
320 })
321 .collect::<Vec<_>>();
322
323 if !matches.is_empty() {
324 type_id_type_subst_map.insert(p.type_id, matches[0].0);
326 } else if engines
327 .te()
328 .get(impl_self_or_trait.implementing_for.initial_type_id())
329 .eq(
330 &*engines.te().get(p.initial_type_id),
331 &PartialEqWithEnginesContext::new(engines),
332 )
333 {
334 type_id_type_subst_map.insert(p.type_id, type_id);
335 }
336 }
337 }
338
339 for parameter in method.parameters.iter_mut() {
341 *parameter.type_argument.type_id_mut() = engines
342 .te()
343 .duplicate(engines, parameter.type_argument.type_id())
344 }
345
346 let mut method_type_subst_map = TypeSubstMap::new();
347 method_type_subst_map.extend(&type_id_type_subst_map);
348 method_type_subst_map.insert(method_implementing_for_typeid, type_id);
349
350 method.subst(&SubstTypesContext::new(
351 engines,
352 &method_type_subst_map,
353 true,
354 ));
355
356 let r = engines
357 .de()
358 .insert(
359 method.clone(),
360 engines.de().get_parsed_decl_id(self.id()).as_ref(),
361 )
362 .with_parent(decl_engine, self.id().into());
363
364 engines.obs().trace(|| {
365 format!(
366 " after get_method_safe_to_unify: {:?}; {:?}",
367 engines.help_out(type_id),
368 engines.help_out(r.id())
369 )
370 });
371
372 return r;
373 }
374
375 engines.obs().trace(|| {
376 format!(
377 " after get_method_safe_to_unify: {:?}; {:?}",
378 engines.help_out(type_id),
379 engines.help_out(self.id())
380 )
381 });
382
383 self.clone()
384 }
385}
386
387impl Named for TyFunctionDecl {
388 fn name(&self) -> &Ident {
389 &self.name
390 }
391}
392
393impl IsConcrete for TyFunctionDecl {
394 fn is_concrete(&self, engines: &Engines) -> bool {
395 self.type_parameters
396 .iter()
397 .all(|tp| tp.is_concrete(engines))
398 && self
399 .return_type
400 .type_id()
401 .is_concrete(engines, TreatNumericAs::Concrete)
402 && self.parameters().iter().all(|t| {
403 t.type_argument
404 .type_id()
405 .is_concrete(engines, TreatNumericAs::Concrete)
406 })
407 }
408}
409impl declaration::FunctionSignature for TyFunctionDecl {
410 fn parameters(&self) -> &Vec<TyFunctionParameter> {
411 &self.parameters
412 }
413
414 fn return_type(&self) -> &GenericArgument {
415 &self.return_type
416 }
417}
418
419impl EqWithEngines for TyFunctionDecl {}
420impl PartialEqWithEngines for TyFunctionDecl {
421 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
422 self.name == other.name
423 && self.body.eq(&other.body, ctx)
424 && self.parameters.eq(&other.parameters, ctx)
425 && self.return_type.eq(&other.return_type, ctx)
426 && self.type_parameters.eq(&other.type_parameters, ctx)
427 && self.visibility == other.visibility
428 && self.is_contract_call == other.is_contract_call
429 && self.purity == other.purity
430 }
431}
432
433impl HashWithEngines for TyFunctionDecl {
434 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
435 let TyFunctionDecl {
436 name,
437 body,
438 parameters,
439 return_type,
440 type_parameters,
441 visibility,
442 is_contract_call,
443 purity,
444 call_path: _,
447 span: _,
448 attributes: _,
449 implementing_type: _,
450 implementing_for_typeid: _,
451 where_clause: _,
452 is_trait_method_dummy: _,
453 is_type_check_finalized: _,
454 kind: _,
455 } = self;
456 name.hash(state);
457 body.hash(state, engines);
458 parameters.hash(state, engines);
459 return_type.hash(state, engines);
460 type_parameters.hash(state, engines);
461 visibility.hash(state);
462 is_contract_call.hash(state);
463 purity.hash(state);
464 }
465}
466
467impl SubstTypes for TyFunctionDecl {
468 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
469 let changes = if ctx.subst_function_body {
470 has_changes! {
471 self.type_parameters.subst(ctx);
472 self.parameters.subst(ctx);
473 self.return_type.subst(ctx);
474 self.body.subst(ctx);
475 self.implementing_for_typeid.subst(ctx);
476 }
477 } else {
478 has_changes! {
479 self.type_parameters.subst(ctx);
480 self.parameters.subst(ctx);
481 self.return_type.subst(ctx);
482 self.implementing_for_typeid.subst(ctx);
483 }
484 };
485
486 if let Some(map) = ctx.type_subst_map.as_ref() {
487 let handler = Handler::default();
488 for (name, value) in &map.const_generics_materialization {
489 let _ = self.materialize_const_generics(ctx.engines, &handler, name, value);
490 }
491 HasChanges::Yes
492 } else {
493 changes
494 }
495 }
496}
497
498impl ReplaceDecls for TyFunctionDecl {
499 fn replace_decls_inner(
500 &mut self,
501 decl_mapping: &DeclMapping,
502 handler: &Handler,
503 ctx: &mut TypeCheckContext,
504 ) -> Result<bool, ErrorEmitted> {
505 let mut func_ctx = ctx.by_ref().with_self_type(self.implementing_for_typeid);
506 self.body
507 .replace_decls(decl_mapping, handler, &mut func_ctx)
508 }
509}
510
511impl Spanned for TyFunctionDecl {
512 fn span(&self) -> Span {
513 self.span.clone()
514 }
515}
516
517impl MonomorphizeHelper for TyFunctionDecl {
518 fn type_parameters(&self) -> &[TypeParameter] {
519 &self.type_parameters
520 }
521
522 fn name(&self) -> &Ident {
523 &self.name
524 }
525
526 fn has_self_type_param(&self) -> bool {
527 false
528 }
529}
530
531impl CollectTypesMetadata for TyFunctionDecl {
532 fn collect_types_metadata(
533 &self,
534 handler: &Handler,
535 ctx: &mut CollectTypesMetadataContext,
536 ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
537 let mut body = vec![];
538 for content in self.body.contents.iter() {
539 body.append(&mut content.collect_types_metadata(handler, ctx)?);
540 }
541 body.append(
542 &mut self
543 .return_type
544 .type_id()
545 .collect_types_metadata(handler, ctx)?,
546 );
547 for p in self.type_parameters.iter() {
548 let p = p
549 .as_type_parameter()
550 .expect("only works for type parameters");
551 body.append(&mut p.type_id.collect_types_metadata(handler, ctx)?);
552 }
553 for param in self.parameters.iter() {
554 body.append(
555 &mut param
556 .type_argument
557 .type_id()
558 .collect_types_metadata(handler, ctx)?,
559 );
560 }
561 Ok(body)
562 }
563}
564
565impl TyFunctionDecl {
566 pub(crate) fn set_implementing_type(&mut self, decl: TyDecl) {
567 self.implementing_type = Some(decl);
568 }
569
570 pub(crate) fn error(decl: &parsed::FunctionDeclaration) -> TyFunctionDecl {
573 let parsed::FunctionDeclaration {
574 name,
575 return_type,
576 span,
577 visibility,
578 purity,
579 where_clause,
580 kind,
581 ..
582 } = decl;
583 TyFunctionDecl {
584 purity: *purity,
585 name: name.clone(),
586 body: <_>::default(),
587 implementing_type: None,
588 implementing_for_typeid: None,
589 span: span.clone(),
590 call_path: CallPath::from(Ident::dummy()),
591 attributes: Default::default(),
592 is_contract_call: false,
593 parameters: Default::default(),
594 visibility: *visibility,
595 return_type: return_type.clone(),
596 type_parameters: Default::default(),
597 where_clause: where_clause.clone(),
598 is_trait_method_dummy: false,
599 is_type_check_finalized: true,
600 kind: match kind {
601 FunctionDeclarationKind::Default => TyFunctionDeclKind::Default,
602 FunctionDeclarationKind::Entry => TyFunctionDeclKind::Entry,
603 FunctionDeclarationKind::Test => TyFunctionDeclKind::Test,
604 FunctionDeclarationKind::Main => TyFunctionDeclKind::Main,
605 },
606 }
607 }
608
609 pub(crate) fn parameters_span(&self) -> Span {
611 if !self.parameters.is_empty() {
612 self.parameters.iter().fold(
613 self.parameters[0].name.span(),
615 |acc, TyFunctionParameter { type_argument, .. }| {
616 Span::join(acc, &type_argument.span())
617 },
618 )
619 } else {
620 self.name.span()
621 }
622 }
623
624 pub fn to_fn_selector_value_untruncated(
625 &self,
626 handler: &Handler,
627 engines: &Engines,
628 ) -> Result<Vec<u8>, ErrorEmitted> {
629 let mut hasher = Sha256::new();
630 let data = self.to_selector_name(handler, engines)?;
631 hasher.update(data);
632 let hash = hasher.finalize();
633 Ok(hash.to_vec())
634 }
635
636 pub fn to_fn_selector_value(
640 &self,
641 handler: &Handler,
642 engines: &Engines,
643 ) -> Result<[u8; 4], ErrorEmitted> {
644 let hash = self.to_fn_selector_value_untruncated(handler, engines)?;
645 let mut buf = [0u8; 4];
647 buf.copy_from_slice(&hash[..4]);
648 Ok(buf)
649 }
650
651 pub fn to_selector_name(
652 &self,
653 handler: &Handler,
654 engines: &Engines,
655 ) -> Result<String, ErrorEmitted> {
656 let named_params = self
657 .parameters
658 .iter()
659 .map(|TyFunctionParameter { type_argument, .. }| {
660 engines
661 .te()
662 .to_typeinfo(type_argument.type_id(), &type_argument.span())
663 .expect("unreachable I think?")
664 .to_selector_name(handler, engines, &type_argument.span())
665 })
666 .filter_map(|name| name.ok())
667 .collect::<Vec<String>>();
668
669 Ok(format!(
670 "{}({})",
671 self.name.as_str(),
672 named_params.join(","),
673 ))
674 }
675
676 pub fn is_entry(&self) -> bool {
678 matches!(self.kind, TyFunctionDeclKind::Entry)
679 }
680
681 pub fn is_main(&self) -> bool {
682 matches!(self.kind, TyFunctionDeclKind::Main)
683 }
684
685 pub fn is_test(&self) -> bool {
687 self.attributes.has_any_of_kind(AttributeKind::Test)
689 }
690
691 pub fn inline(&self) -> Option<Inline> {
692 self.attributes.inline()
693 }
694
695 pub fn trace(&self) -> Option<Trace> {
696 self.attributes.trace()
697 }
698
699 pub fn is_fallback(&self) -> bool {
700 self.attributes.has_any_of_kind(AttributeKind::Fallback)
701 }
702
703 pub fn is_constructor(&self, engines: &Engines, type_id: TypeId) -> Option<bool> {
708 if self
709 .parameters
710 .first()
711 .map(|param| param.is_self())
712 .unwrap_or_default()
713 {
714 return Some(false);
715 };
716
717 match &self.implementing_type {
718 Some(TyDecl::ImplSelfOrTrait(t)) => {
719 let unify_check = UnifyCheck::non_dynamic_equality(engines);
720
721 let implementing_for = engines.de().get(&t.decl_id).implementing_for.type_id();
722
723 if unify_check.check(type_id, implementing_for)
729 && unify_check.check(type_id, self.return_type.type_id())
730 {
731 Some(true)
732 } else {
733 None
734 }
735 }
736 _ => Some(false),
737 }
738 }
739
740 pub fn is_from_blanket_impl(&self, engines: &Engines) -> bool {
741 if let Some(TyDecl::ImplSelfOrTrait(existing_impl_trait)) = self.implementing_type.clone() {
742 let existing_trait_decl = engines
743 .de()
744 .get_impl_self_or_trait(&existing_impl_trait.decl_id);
745 if !existing_trait_decl.impl_type_parameters.is_empty()
746 && matches!(
747 *engines
748 .te()
749 .get(existing_trait_decl.implementing_for.type_id()),
750 TypeInfo::UnknownGeneric { .. }
751 )
752 {
753 return true;
754 }
755 }
756 false
757 }
758}
759
760#[derive(Debug, Clone, Serialize, Deserialize)]
761pub struct TyFunctionParameter {
762 pub name: Ident,
763 pub is_reference: bool,
764 pub is_mutable: bool,
765 pub mutability_span: Span,
766 pub type_argument: GenericArgument,
767}
768
769impl EqWithEngines for TyFunctionParameter {}
770impl PartialEqWithEngines for TyFunctionParameter {
771 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
772 self.name == other.name
773 && self.type_argument.eq(&other.type_argument, ctx)
774 && self.is_reference == other.is_reference
775 && self.is_mutable == other.is_mutable
776 }
777}
778
779impl HashWithEngines for TyFunctionParameter {
780 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
781 let TyFunctionParameter {
782 name,
783 is_reference,
784 is_mutable,
785 type_argument,
786 mutability_span: _,
789 } = self;
790 name.hash(state);
791 type_argument.hash(state, engines);
792 is_reference.hash(state);
793 is_mutable.hash(state);
794 }
795}
796
797impl SubstTypes for TyFunctionParameter {
798 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
799 self.type_argument.type_id_mut().subst(ctx)
800 }
801}
802
803impl TyFunctionParameter {
804 pub fn is_self(&self) -> bool {
805 self.name.as_str() == "self"
806 }
807}
808
809#[derive(Clone, Debug, PartialEq, Eq, Hash)]
810pub enum TyFunctionSigTypeParameter {
811 Type(TypeId),
812 Const(ConstGenericExpr),
813}
814
815#[derive(Clone, Debug, PartialEq, Eq, Hash)]
816pub struct TyFunctionSig {
817 pub return_type: TypeId,
818 pub parameters: Vec<TypeId>,
819 pub type_parameters: Vec<TyFunctionSigTypeParameter>,
820}
821
822impl DisplayWithEngines for TyFunctionSig {
823 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
824 write!(f, "{:?}", engines.help_out(self))
825 }
826}
827
828impl DebugWithEngines for TyFunctionSig {
829 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
830 let tp_str = if self.type_parameters.is_empty() {
831 "".to_string()
832 } else {
833 format!(
834 "<{}>",
835 self.type_parameters
836 .iter()
837 .map(|p| match p {
838 TyFunctionSigTypeParameter::Type(t) => format!("{:?}", engines.help_out(t)),
839 TyFunctionSigTypeParameter::Const(expr) =>
840 format!("{:?}", engines.help_out(expr)),
841 })
842 .collect::<Vec<_>>()
843 .join(", "),
844 )
845 };
846 write!(
847 f,
848 "fn{}({}) -> {}",
849 tp_str,
850 self.parameters
851 .iter()
852 .map(|p| format!("{}", engines.help_out(p)))
853 .collect::<Vec<_>>()
854 .join(", "),
855 engines.help_out(self.return_type),
856 )
857 }
858}
859
860impl TyFunctionSig {
861 pub fn from_fn_decl(fn_decl: &TyFunctionDecl) -> Self {
862 Self {
863 return_type: fn_decl.return_type.type_id(),
864 parameters: fn_decl
865 .parameters
866 .iter()
867 .map(|p| p.type_argument.type_id())
868 .collect::<Vec<_>>(),
869 type_parameters: fn_decl
870 .type_parameters
871 .iter()
872 .map(|x| match x {
873 TypeParameter::Type(p) => TyFunctionSigTypeParameter::Type(p.type_id),
874 TypeParameter::Const(p) => {
875 let expr = ConstGenericExpr::AmbiguousVariableExpression {
876 ident: p.name.clone(),
877 decl: None,
878 };
879 TyFunctionSigTypeParameter::Const(p.expr.clone().unwrap_or(expr))
880 }
881 })
882 .collect(),
883 }
884 }
885
886 pub fn is_concrete(&self, engines: &Engines) -> bool {
887 self.return_type
888 .is_concrete(engines, TreatNumericAs::Concrete)
889 && self
890 .parameters
891 .iter()
892 .all(|p| p.is_concrete(engines, TreatNumericAs::Concrete))
893 && self.type_parameters.iter().all(|x| match x {
894 TyFunctionSigTypeParameter::Type(type_id) => {
895 type_id.is_concrete(engines, TreatNumericAs::Concrete)
896 }
897 TyFunctionSigTypeParameter::Const(expr) => match expr {
898 ConstGenericExpr::Literal { .. } => true,
899 ConstGenericExpr::AmbiguousVariableExpression { .. } => false,
900 },
901 })
902 }
903
904 pub fn get_type_str(&self, engines: &Engines) -> String {
908 let tp_str = if self.type_parameters.is_empty() {
909 "".to_string()
910 } else {
911 format!(
912 "<{}>",
913 self.type_parameters
914 .iter()
915 .map(|x| match x {
916 TyFunctionSigTypeParameter::Type(type_id) => type_id.get_type_str(engines),
917 TyFunctionSigTypeParameter::Const(p) => {
918 match p {
919 ConstGenericExpr::Literal { val, .. } => val.to_string(),
920 ConstGenericExpr::AmbiguousVariableExpression { ident, .. } => {
921 ident.as_str().to_string()
922 }
923 }
924 }
925 })
926 .collect::<Vec<_>>()
927 .join(", "),
928 )
929 };
930 format!(
931 "fn{}({}) -> {}",
932 tp_str,
933 self.parameters
934 .iter()
935 .map(|p| p.get_type_str(engines))
936 .collect::<Vec<_>>()
937 .join(", "),
938 self.return_type.get_type_str(engines),
939 )
940 }
941}