1use crate::{
2 ast_elements::type_argument::GenericTypeArgument,
3 decl_engine::*,
4 engine_threading::*,
5 has_changes,
6 language::{
7 parsed::{self, FunctionDeclaration, FunctionDeclarationKind},
8 ty::*,
9 CallPath, Inline, Purity, Trace, Visibility,
10 },
11 semantic_analysis::TypeCheckContext,
12 transform::{self, AttributeKind},
13 type_system::*,
14 types::*,
15 HasChanges,
16};
17use ast_elements::type_parameter::ConstGenericExpr;
18use either::Either;
19use monomorphization::MonomorphizeHelper;
20use serde::{Deserialize, Serialize};
21use sha2::{Digest, Sha256};
22use std::{
23 collections::BTreeMap,
24 fmt,
25 hash::{Hash, Hasher},
26};
27use sway_error::handler::{ErrorEmitted, Handler};
28use sway_types::{Ident, Named, Span, Spanned};
29
30#[derive(Clone, Debug, Serialize, Deserialize)]
31pub enum TyFunctionDeclKind {
32 Default,
33 Entry,
34 Main,
35 Test,
36}
37
38#[derive(Clone, Debug, Serialize, Deserialize)]
39pub struct TyFunctionDecl {
40 pub name: Ident,
41 pub body: TyCodeBlock,
42 pub parameters: Vec<TyFunctionParameter>,
43 pub implementing_type: Option<TyDecl>,
59 pub implementing_for: Option<TypeId>,
75 pub span: Span,
76 pub call_path: CallPath,
82 pub attributes: transform::Attributes,
83 pub type_parameters: Vec<TypeParameter>,
84 pub return_type: GenericTypeArgument,
85 pub visibility: Visibility,
86 pub is_contract_call: bool,
88 pub purity: Purity,
89 pub where_clause: Vec<(Ident, Vec<TraitConstraint>)>,
90 pub is_trait_method_dummy: bool,
91 pub is_type_check_finalized: bool,
92 pub kind: TyFunctionDeclKind,
99}
100
101impl TyDeclParsedType for TyFunctionDecl {
102 type ParsedType = FunctionDeclaration;
103}
104
105impl DebugWithEngines for TyFunctionDecl {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
107 write!(
108 f,
109 "{}{:?}{}({}): {:?} -> {:?}",
110 if self.is_trait_method_dummy {
111 "dummy ".to_string()
112 } else {
113 "".to_string()
114 },
115 self.name,
116 if !self.type_parameters.is_empty() {
117 format!(
118 "<{}>",
119 self.type_parameters
120 .iter()
121 .map(|p| format!("{:?}", engines.help_out(p)))
122 .collect::<Vec<_>>()
123 .join(", ")
124 )
125 } else {
126 "".to_string()
127 },
128 self.parameters
129 .iter()
130 .map(|p| format!(
131 "{}: {:?} -> {:?}",
132 p.name.as_str(),
133 engines.help_out(p.type_argument.initial_type_id),
134 engines.help_out(p.type_argument.type_id)
135 ))
136 .collect::<Vec<_>>()
137 .join(", "),
138 engines.help_out(self.return_type.initial_type_id),
139 engines.help_out(self.return_type.type_id),
140 )
141 }
142}
143
144impl DisplayWithEngines for TyFunctionDecl {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
146 write!(
147 f,
148 "{}{}({}) -> {}",
149 self.name,
150 if !self.type_parameters.is_empty() {
151 format!(
152 "<{}>",
153 self.type_parameters
154 .iter()
155 .map(|p| {
156 let p = p
157 .as_type_parameter()
158 .expect("only works for type parameters");
159 format!("{}", engines.help_out(p.initial_type_id))
160 })
161 .collect::<Vec<_>>()
162 .join(", ")
163 )
164 } else {
165 "".to_string()
166 },
167 self.parameters
168 .iter()
169 .map(|p| format!(
170 "{}: {}",
171 p.name.as_str(),
172 engines.help_out(p.type_argument.initial_type_id)
173 ))
174 .collect::<Vec<_>>()
175 .join(", "),
176 engines.help_out(self.return_type.initial_type_id),
177 )
178 }
179}
180
181impl MaterializeConstGenerics for TyFunctionDecl {
182 fn materialize_const_generics(
183 &mut self,
184 engines: &Engines,
185 handler: &Handler,
186 name: &str,
187 value: &TyExpression,
188 ) -> Result<HasChanges, ErrorEmitted> {
189 let mut has_changes = HasChanges::No;
190 for tp in self.type_parameters.iter_mut() {
191 match tp {
192 TypeParameter::Type(p) => {
193 has_changes |= p
194 .type_id
195 .materialize_const_generics(engines, handler, name, value)?;
196 }
197 TypeParameter::Const(p) if p.name.as_str() == name => match p.expr.as_ref() {
198 Some(v) => {
199 assert!(
200 v.as_literal_val().unwrap() as u64
201 == value
202 .extract_literal_value()
203 .unwrap()
204 .cast_value_to_u64()
205 .unwrap()
206 );
207 }
208 None => {
209 p.expr = Some(ConstGenericExpr::from_ty_expression(handler, value)?);
210 has_changes = HasChanges::Yes;
211 }
212 },
213 _ => {}
214 }
215 }
216
217 for param in self.parameters.iter_mut() {
218 has_changes |= param
219 .type_argument
220 .type_id
221 .materialize_const_generics(engines, handler, name, value)?;
222 }
223 has_changes |= self
224 .return_type
225 .type_id
226 .materialize_const_generics(engines, handler, name, value)?;
227 has_changes |= self
228 .body
229 .materialize_const_generics(engines, handler, name, value)?;
230 Ok(has_changes)
231 }
232}
233
234fn rename_const_generics_on_function(
239 handler: &Handler,
240 engines: &Engines,
241 impl_self_or_trait: &TyImplSelfOrTrait,
242 function: &mut TyFunctionDecl,
243) -> HasChanges {
244 let from = impl_self_or_trait.implementing_for.initial_type_id;
245 let to = impl_self_or_trait.implementing_for.type_id;
246
247 let from = engines.te().get(from);
248 let to = engines.te().get(to);
249
250 match (&*from, &*to) {
251 (
252 TypeInfo::Custom {
253 type_arguments: Some(type_arguments),
254 ..
255 },
256 TypeInfo::Struct(s),
257 ) => {
258 let decl = engines.de().get(s);
259 rename_const_generics_on_function_inner(
260 handler,
261 engines,
262 function,
263 type_arguments,
264 decl.type_parameters(),
265 )
266 }
267 (
268 TypeInfo::Custom {
269 type_arguments: Some(type_arguments),
270 ..
271 },
272 TypeInfo::Enum(s),
273 ) => {
274 let decl = engines.de().get(s);
275 rename_const_generics_on_function_inner(
276 handler,
277 engines,
278 function,
279 type_arguments,
280 decl.type_parameters(),
281 )
282 }
283 _ => HasChanges::No,
284 }
285}
286
287fn rename_const_generics_on_function_inner(
288 handler: &Handler,
289 engines: &Engines,
290 function: &mut TyFunctionDecl,
291 type_arguments: &[GenericArgument],
292 generic_parameters: &[TypeParameter],
293) -> HasChanges {
294 let mut has_changes = HasChanges::No;
295 for a in type_arguments.iter().zip(generic_parameters.iter()) {
296 match (a.0, a.1) {
297 (GenericArgument::Type(a), TypeParameter::Const(b)) => {
298 let mut type_subst_map = TypeSubstMap::default();
300 type_subst_map.const_generics_renaming.insert(
301 a.call_path_tree
302 .as_ref()
303 .unwrap()
304 .qualified_call_path
305 .call_path
306 .suffix
307 .clone(),
308 b.name.clone(),
309 );
310 has_changes |= function.subst_inner(&SubstTypesContext {
311 handler,
312 engines,
313 type_subst_map: Some(&type_subst_map),
314 subst_function_body: true,
315 });
316 }
317 (GenericArgument::Const(a), TypeParameter::Const(b)) => {
318 engines
319 .obs()
320 .trace(|| format!("{:?} -> {:?}", a.expr, b.expr));
321 }
322 _ => {}
323 }
324 }
325 has_changes
326}
327
328impl DeclRefFunction {
329 pub fn get_method_safe_to_unify(
334 &self,
335 handler: &Handler,
336 engines: &Engines,
337 type_id: TypeId,
338 ) -> Self {
339 engines.obs().trace(|| {
340 format!(
341 " before get_method_safe_to_unify: {:?} {:?}",
342 engines.help_out(type_id),
343 engines.help_out(self.id())
344 )
345 });
346
347 let decl_engine = engines.de();
348
349 let original = &*decl_engine.get_function(self);
350
351 if let Some(method_implementing_for) = original.implementing_for {
352 let mut method = original.clone();
353
354 let mut type_id_type_subst_map = TypeSubstMap::new();
355
356 let mut has_changes = HasChanges::No;
357 if let Some(TyDecl::ImplSelfOrTrait(t)) = &method.implementing_type {
358 let impl_self_or_trait = &*engines.de().get(&t.decl_id);
359 has_changes |= rename_const_generics_on_function(
360 handler,
361 engines,
362 impl_self_or_trait,
363 &mut method,
364 );
365
366 let mut type_id_type_parameters = vec![];
367 let mut const_generic_parameters = BTreeMap::default();
368 type_id.extract_type_parameters(
369 handler,
370 engines,
371 0,
372 &mut type_id_type_parameters,
373 &mut const_generic_parameters,
374 impl_self_or_trait.implementing_for.type_id,
375 );
376
377 type_id_type_subst_map
378 .const_generics_materialization
379 .append(&mut const_generic_parameters);
380
381 for p in impl_self_or_trait
382 .impl_type_parameters
383 .iter()
384 .filter_map(|x| x.as_type_parameter())
385 {
386 let matches = type_id_type_parameters
387 .iter()
388 .filter(|(_, orig_tp)| {
389 engines.te().get(*orig_tp).eq(
390 &*engines.te().get(p.type_id),
391 &PartialEqWithEnginesContext::new(engines),
392 )
393 })
394 .collect::<Vec<_>>();
395
396 if !matches.is_empty() {
397 type_id_type_subst_map.insert(p.type_id, matches[0].0);
399 } else if engines
400 .te()
401 .get(impl_self_or_trait.implementing_for.initial_type_id)
402 .eq(
403 &*engines.te().get(p.initial_type_id),
404 &PartialEqWithEnginesContext::new(engines),
405 )
406 {
407 type_id_type_subst_map.insert(p.type_id, type_id);
408 }
409 }
410 }
411
412 for parameter in method.parameters.iter_mut() {
425 parameter.type_argument.type_id = engines
426 .te()
427 .duplicate(engines, parameter.type_argument.type_id)
428 }
429
430 let mut method_type_subst_map = TypeSubstMap::new();
431 method_type_subst_map.extend(&type_id_type_subst_map);
432 method_type_subst_map.insert(method_implementing_for, type_id);
433
434 has_changes |= method.subst(&SubstTypesContext::new(
435 handler,
436 engines,
437 &method_type_subst_map,
438 true,
439 ));
440
441 let decl_ref = if has_changes.has_changes() {
442 engines
443 .de()
444 .insert(
445 method.clone(),
446 engines.de().get_parsed_decl_id(self.id()).as_ref(),
447 )
448 .with_parent(decl_engine, self.id().into())
449 } else {
450 self.clone()
451 };
452
453 engines.obs().trace(|| {
454 format!(
455 " after get_method_safe_to_unify: {:?}; {:?}",
456 engines.help_out(type_id),
457 engines.help_out(decl_ref.id())
458 )
459 });
460
461 return decl_ref;
462 }
463
464 engines.obs().trace(|| {
465 format!(
466 " after get_method_safe_to_unify: {:?}; {:?}",
467 engines.help_out(type_id),
468 engines.help_out(self.id())
469 )
470 });
471
472 self.clone()
473 }
474}
475
476impl Named for TyFunctionDecl {
477 fn name(&self) -> &Ident {
478 &self.name
479 }
480}
481
482impl IsConcrete for TyFunctionDecl {
483 fn is_concrete(&self, handler: &Handler, engines: &Engines) -> bool {
484 self.type_parameters
485 .iter()
486 .all(|tp| tp.is_concrete(handler, engines))
487 && self
488 .return_type
489 .type_id
490 .is_concrete(engines, TreatNumericAs::Concrete)
491 && self.parameters().iter().all(|t| {
492 t.type_argument
493 .type_id
494 .is_concrete(engines, TreatNumericAs::Concrete)
495 })
496 }
497}
498impl declaration::FunctionSignature for TyFunctionDecl {
499 fn parameters(&self) -> &Vec<TyFunctionParameter> {
500 &self.parameters
501 }
502
503 fn return_type(&self) -> &GenericTypeArgument {
504 &self.return_type
505 }
506}
507
508impl EqWithEngines for TyFunctionDecl {}
509impl PartialEqWithEngines for TyFunctionDecl {
510 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
511 self.name == other.name
512 && self.body.eq(&other.body, ctx)
513 && self.parameters.eq(&other.parameters, ctx)
514 && self.return_type.eq(&other.return_type, ctx)
515 && self.type_parameters.eq(&other.type_parameters, ctx)
516 && self.visibility == other.visibility
517 && self.is_contract_call == other.is_contract_call
518 && self.purity == other.purity
519 && self.call_path == other.call_path
520 && self.span == other.span
521 }
522}
523
524impl HashWithEngines for TyFunctionDecl {
525 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
526 let TyFunctionDecl {
527 name,
528 body,
529 parameters,
530 return_type,
531 type_parameters,
532 visibility,
533 is_contract_call,
534 purity,
535 call_path,
536 span,
537 attributes: _,
540 implementing_type: _,
541 implementing_for: _,
542 where_clause: _,
543 is_trait_method_dummy: _,
544 is_type_check_finalized: _,
545 kind: _,
546 } = self;
547 name.hash(state);
548 body.hash(state, engines);
549 parameters.hash(state, engines);
550 return_type.hash(state, engines);
551 type_parameters.hash(state, engines);
552 visibility.hash(state);
553 is_contract_call.hash(state);
554 purity.hash(state);
555 call_path.hash(state);
556 span.hash(state);
557 }
558}
559
560impl SubstTypes for TyFunctionDecl {
561 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
562 let mut has_changes = if ctx.subst_function_body {
563 has_changes! {
564 self.type_parameters.subst(ctx);
565 self.parameters.subst(ctx);
566 self.return_type.subst(ctx);
567 self.body.subst(ctx);
568 self.implementing_for.subst(ctx);
569 }
570 } else {
571 has_changes! {
572 self.type_parameters.subst(ctx);
573 self.parameters.subst(ctx);
574 self.return_type.subst(ctx);
575 self.implementing_for.subst(ctx);
576 }
577 };
578
579 if let Some(map) = ctx.type_subst_map.as_ref() {
580 let handler = Handler::default();
581 for (name, value) in &map.const_generics_materialization {
582 if let Ok(materialization_has_changes) =
583 self.materialize_const_generics(ctx.engines, &handler, name, value)
584 {
585 has_changes |= materialization_has_changes;
586 }
587 }
588 }
589
590 has_changes
591 }
592}
593
594impl ReplaceDecls for TyFunctionDecl {
595 fn replace_decls_inner(
596 &mut self,
597 decl_mapping: &DeclMapping,
598 handler: &Handler,
599 ctx: &mut TypeCheckContext,
600 ) -> Result<HasChanges, ErrorEmitted> {
601 let mut func_ctx = ctx.by_ref().with_self_type(self.implementing_for);
602 self.body
603 .replace_decls(decl_mapping, handler, &mut func_ctx)
604 }
605}
606
607impl Spanned for TyFunctionDecl {
608 fn span(&self) -> Span {
609 self.span.clone()
610 }
611}
612
613impl MonomorphizeHelper for TyFunctionDecl {
614 fn type_parameters(&self) -> &[TypeParameter] {
615 &self.type_parameters
616 }
617
618 fn name(&self) -> &Ident {
619 &self.name
620 }
621
622 fn has_self_type_param(&self) -> bool {
623 false
624 }
625}
626
627impl CollectTypesMetadata for TyFunctionDecl {
628 fn collect_types_metadata(
629 &self,
630 handler: &Handler,
631 ctx: &mut CollectTypesMetadataContext,
632 ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
633 let mut body = vec![];
634 for content in self.body.contents.iter() {
635 body.append(&mut content.collect_types_metadata(handler, ctx)?);
636 }
637 body.append(
638 &mut self
639 .return_type
640 .type_id
641 .collect_types_metadata(handler, ctx)?,
642 );
643 for p in self.type_parameters.iter() {
644 let p = p
645 .as_type_parameter()
646 .expect("only works for type parameters");
647 body.append(&mut p.type_id.collect_types_metadata(handler, ctx)?);
648 }
649 for param in self.parameters.iter() {
650 body.append(
651 &mut param
652 .type_argument
653 .type_id
654 .collect_types_metadata(handler, ctx)?,
655 );
656 }
657 Ok(body)
658 }
659}
660
661impl TyFunctionDecl {
662 pub(crate) fn set_implementing_type(&mut self, decl: TyDecl) {
663 self.implementing_type = Some(decl);
664 }
665
666 pub(crate) fn error(decl: &parsed::FunctionDeclaration) -> TyFunctionDecl {
669 let parsed::FunctionDeclaration {
670 name,
671 return_type,
672 span,
673 visibility,
674 purity,
675 where_clause,
676 kind,
677 ..
678 } = decl;
679 TyFunctionDecl {
680 purity: *purity,
681 name: name.clone(),
682 body: <_>::default(),
683 implementing_type: None,
684 implementing_for: None,
685 span: span.clone(),
686 call_path: CallPath::from(Ident::dummy()),
687 attributes: Default::default(),
688 is_contract_call: false,
689 parameters: Default::default(),
690 visibility: *visibility,
691 return_type: return_type.clone(),
692 type_parameters: Default::default(),
693 where_clause: where_clause.clone(),
694 is_trait_method_dummy: false,
695 is_type_check_finalized: true,
696 kind: match kind {
697 FunctionDeclarationKind::Default => TyFunctionDeclKind::Default,
698 FunctionDeclarationKind::Entry => TyFunctionDeclKind::Entry,
699 FunctionDeclarationKind::Test => TyFunctionDeclKind::Test,
700 FunctionDeclarationKind::Main => TyFunctionDeclKind::Main,
701 },
702 }
703 }
704
705 pub(crate) fn parameters_span(&self) -> Span {
707 if !self.parameters.is_empty() {
708 self.parameters.iter().fold(
709 self.parameters[0].name.span(),
711 |acc, TyFunctionParameter { type_argument, .. }| {
712 Span::join(acc, &type_argument.span)
713 },
714 )
715 } else {
716 self.name.span()
717 }
718 }
719
720 pub fn to_fn_selector_value_untruncated(
721 &self,
722 handler: &Handler,
723 engines: &Engines,
724 ) -> Result<Vec<u8>, ErrorEmitted> {
725 let mut hasher = Sha256::new();
726 let data = self.to_selector_name(handler, engines)?;
727 hasher.update(data);
728 let hash = hasher.finalize();
729 Ok(hash.to_vec())
730 }
731
732 pub fn to_fn_selector_value(
736 &self,
737 handler: &Handler,
738 engines: &Engines,
739 ) -> Result<[u8; 4], ErrorEmitted> {
740 let hash = self.to_fn_selector_value_untruncated(handler, engines)?;
741 let mut buf = [0u8; 4];
743 buf.copy_from_slice(&hash[..4]);
744 Ok(buf)
745 }
746
747 pub fn to_selector_name(
748 &self,
749 handler: &Handler,
750 engines: &Engines,
751 ) -> Result<String, ErrorEmitted> {
752 let named_params = self
753 .parameters
754 .iter()
755 .map(|TyFunctionParameter { type_argument, .. }| {
756 engines
757 .te()
758 .to_typeinfo(type_argument.type_id, &type_argument.span)
759 .expect("unreachable I think?")
760 .to_selector_name(handler, engines, &type_argument.span)
761 })
762 .filter_map(|name| name.ok())
763 .collect::<Vec<String>>();
764
765 Ok(format!(
766 "{}({})",
767 self.name.as_str(),
768 named_params.join(","),
769 ))
770 }
771
772 pub fn is_default(&self) -> bool {
773 !(self.is_entry() || self.is_main() || self.is_test())
776 }
777
778 pub fn is_entry(&self) -> bool {
780 matches!(self.kind, TyFunctionDeclKind::Entry)
781 }
782
783 pub fn is_main(&self) -> bool {
784 matches!(self.kind, TyFunctionDeclKind::Main)
785 }
786
787 pub fn is_test(&self) -> bool {
789 self.attributes.has_any_of_kind(AttributeKind::Test)
792 }
793
794 pub fn inline(&self) -> Option<Inline> {
795 self.attributes.inline()
796 }
797
798 pub fn trace(&self) -> Option<Trace> {
799 self.attributes.trace()
800 }
801
802 pub fn is_fallback(&self) -> bool {
803 self.attributes.has_any_of_kind(AttributeKind::Fallback)
804 }
805
806 pub fn is_constructor(&self, engines: &Engines, type_id: TypeId) -> Option<bool> {
811 if self
812 .parameters
813 .first()
814 .map(|param| param.is_self())
815 .unwrap_or_default()
816 {
817 return Some(false);
818 };
819
820 match &self.implementing_type {
821 Some(TyDecl::ImplSelfOrTrait(t)) => {
822 let unify_check = UnifyCheck::non_dynamic_equality(engines);
823
824 let implementing_for = engines.de().get(&t.decl_id).implementing_for.type_id;
825
826 if unify_check.check(type_id, implementing_for)
832 && unify_check.check(type_id, self.return_type.type_id)
833 {
834 Some(true)
835 } else {
836 None
837 }
838 }
839 _ => Some(false),
840 }
841 }
842
843 pub fn is_from_blanket_impl(&self, engines: &Engines) -> bool {
844 if let Some(TyDecl::ImplSelfOrTrait(existing_impl_trait)) = &self.implementing_type {
845 let existing_trait_decl = engines
846 .de()
847 .get_impl_self_or_trait(&existing_impl_trait.decl_id);
848 if !existing_trait_decl.impl_type_parameters.is_empty()
849 && matches!(
850 *engines
851 .te()
852 .get(existing_trait_decl.implementing_for.type_id),
853 TypeInfo::UnknownGeneric { .. }
854 )
855 {
856 return true;
857 }
858 }
859 false
860 }
861}
862
863#[derive(Debug, Clone, Serialize, Deserialize)]
864pub struct TyFunctionParameter {
865 pub name: Ident,
866 pub is_reference: bool,
867 pub is_mutable: bool,
868 pub mutability_span: Span,
869 pub type_argument: GenericTypeArgument,
870}
871
872impl EqWithEngines for TyFunctionParameter {}
873impl PartialEqWithEngines for TyFunctionParameter {
874 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
875 self.name == other.name
876 && self.type_argument.eq(&other.type_argument, ctx)
877 && self.is_reference == other.is_reference
878 && self.is_mutable == other.is_mutable
879 }
880}
881
882impl HashWithEngines for TyFunctionParameter {
883 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
884 let TyFunctionParameter {
885 name,
886 is_reference,
887 is_mutable,
888 type_argument,
889 mutability_span: _,
892 } = self;
893 name.hash(state);
894 type_argument.hash(state, engines);
895 is_reference.hash(state);
896 is_mutable.hash(state);
897 }
898}
899
900impl SubstTypes for TyFunctionParameter {
901 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
902 self.type_argument.type_id.subst(ctx)
903 }
904}
905
906impl TyFunctionParameter {
907 pub fn is_self(&self) -> bool {
908 self.name.as_str() == "self"
909 }
910}
911
912#[derive(Clone, Debug, PartialEq, Eq, Hash)]
913pub enum TyFunctionSigTypeParameter {
914 Type(TypeId),
915 Const(ConstGenericExpr),
916}
917
918#[derive(Clone, Debug, PartialEq, Eq, Hash)]
919pub struct TyFunctionSig {
920 pub return_type: TypeId,
921 pub parameters: Vec<TypeId>,
922 pub type_parameters: Vec<TyFunctionSigTypeParameter>,
923}
924
925impl DisplayWithEngines for TyFunctionSig {
926 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
927 write!(f, "{:?}", engines.help_out(self))
928 }
929}
930
931impl DebugWithEngines for TyFunctionSig {
932 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
933 let tp_str = if self.type_parameters.is_empty() {
934 "".to_string()
935 } else {
936 format!(
937 "<{}>",
938 self.type_parameters
939 .iter()
940 .map(|p| match p {
941 TyFunctionSigTypeParameter::Type(t) => format!("{:?}", engines.help_out(t)),
942 TyFunctionSigTypeParameter::Const(expr) =>
943 format!("{:?}", engines.help_out(expr)),
944 })
945 .collect::<Vec<_>>()
946 .join(", "),
947 )
948 };
949 write!(
950 f,
951 "fn{}({}) -> {}",
952 tp_str,
953 self.parameters
954 .iter()
955 .map(|p| format!("{}", engines.help_out(p)))
956 .collect::<Vec<_>>()
957 .join(", "),
958 engines.help_out(self.return_type),
959 )
960 }
961}
962
963impl TyFunctionSig {
964 pub fn from_fn_decl(fn_decl: &TyFunctionDecl) -> Self {
965 Self {
966 return_type: fn_decl.return_type.type_id,
967 parameters: fn_decl
968 .parameters
969 .iter()
970 .map(|p| p.type_argument.type_id)
971 .collect::<Vec<_>>(),
972 type_parameters: fn_decl
973 .type_parameters
974 .iter()
975 .map(|x| match x {
976 TypeParameter::Type(p) => TyFunctionSigTypeParameter::Type(p.type_id),
977 TypeParameter::Const(p) => {
978 let expr = ConstGenericExpr::AmbiguousVariableExpression {
979 ident: p.name.clone(),
980 decl: None,
981 };
982 TyFunctionSigTypeParameter::Const(p.expr.clone().unwrap_or(expr))
983 }
984 })
985 .collect(),
986 }
987 }
988
989 pub fn is_concrete(&self, engines: &Engines) -> bool {
990 self.return_type
991 .is_concrete(engines, TreatNumericAs::Concrete)
992 && self
993 .parameters
994 .iter()
995 .all(|p| p.is_concrete(engines, TreatNumericAs::Concrete))
996 && self.type_parameters.iter().all(|x| match x {
997 TyFunctionSigTypeParameter::Type(type_id) => {
998 type_id.is_concrete(engines, TreatNumericAs::Concrete)
999 }
1000 TyFunctionSigTypeParameter::Const(expr) => match expr {
1001 ConstGenericExpr::Literal { .. } => true,
1002 ConstGenericExpr::AmbiguousVariableExpression { .. } => false,
1003 },
1004 })
1005 }
1006
1007 pub fn get_type_str(&self, engines: &Engines) -> String {
1011 let tp_str = if self.type_parameters.is_empty() {
1012 "".to_string()
1013 } else {
1014 format!(
1015 "<{}>",
1016 self.type_parameters
1017 .iter()
1018 .map(|x| match x {
1019 TyFunctionSigTypeParameter::Type(type_id) => type_id.get_type_str(engines),
1020 TyFunctionSigTypeParameter::Const(p) => {
1021 match p {
1022 ConstGenericExpr::Literal { val, .. } => val.to_string(),
1023 ConstGenericExpr::AmbiguousVariableExpression { ident, .. } => {
1024 ident.as_str().to_string()
1025 }
1026 }
1027 }
1028 })
1029 .collect::<Vec<_>>()
1030 .join(", "),
1031 )
1032 };
1033 format!(
1034 "fn{}({}) -> {}",
1035 tp_str,
1036 self.parameters
1037 .iter()
1038 .map(|p| p.get_type_str(engines))
1039 .collect::<Vec<_>>()
1040 .join(", "),
1041 self.return_type.get_type_str(engines),
1042 )
1043 }
1044}
1045
1046#[derive(Debug, Clone, Copy)]
1076pub struct TyFunctionDisplay {
1077 display_self_type: bool,
1084 display_trait: bool,
1087 display_module_fn_call_path: bool,
1090 display_fn_type_params: bool,
1093 display_self_param_type: bool,
1098 display_ref_mut: bool,
1101 display_param_names: bool,
1104 display_param_types: bool,
1107 display_return_type: bool,
1110 types_display: TypeInfoDisplay,
1117}
1118
1119impl TyFunctionDisplay {
1120 pub const fn only_name() -> Self {
1121 Self {
1122 display_trait: false,
1123 display_self_type: false,
1124 display_module_fn_call_path: false,
1125 display_fn_type_params: false,
1126 display_self_param_type: false,
1127 display_ref_mut: false,
1128 display_param_names: false,
1129 display_param_types: false,
1130 display_return_type: false,
1131 types_display: TypeInfoDisplay::only_name(),
1132 }
1133 }
1134
1135 pub const fn full() -> Self {
1136 Self {
1137 display_trait: true,
1138 display_self_type: true,
1139 display_module_fn_call_path: true,
1140 display_fn_type_params: true,
1141 display_self_param_type: true,
1142 display_ref_mut: true,
1143 display_param_names: true,
1144 display_param_types: true,
1145 display_return_type: true,
1146 types_display: TypeInfoDisplay::full(),
1147 }
1148 }
1149
1150 pub const fn with_trait(self) -> Self {
1151 Self {
1152 display_trait: true,
1153 ..self
1154 }
1155 }
1156
1157 pub const fn without_trait(self) -> Self {
1158 Self {
1159 display_trait: false,
1160 ..self
1161 }
1162 }
1163
1164 pub const fn with_self_type(self) -> Self {
1165 Self {
1166 display_self_type: true,
1167 ..self
1168 }
1169 }
1170
1171 pub const fn without_self_type(self) -> Self {
1172 Self {
1173 display_self_type: false,
1174 ..self
1175 }
1176 }
1177
1178 pub const fn with_module_fn_call_path(self) -> Self {
1179 Self {
1180 display_module_fn_call_path: true,
1181 ..self
1182 }
1183 }
1184
1185 pub const fn without_module_fn_call_path(self) -> Self {
1186 Self {
1187 display_module_fn_call_path: false,
1188 ..self
1189 }
1190 }
1191
1192 pub const fn with_fn_type_params(self) -> Self {
1193 Self {
1194 display_fn_type_params: true,
1195 ..self
1196 }
1197 }
1198
1199 pub const fn without_fn_type_params(self) -> Self {
1200 Self {
1201 display_fn_type_params: false,
1202 ..self
1203 }
1204 }
1205
1206 pub const fn with_self_param_type(self) -> Self {
1207 Self {
1208 display_self_param_type: true,
1209 ..self
1210 }
1211 }
1212
1213 pub const fn without_self_param_type(self) -> Self {
1214 Self {
1215 display_self_param_type: false,
1216 ..self
1217 }
1218 }
1219
1220 pub const fn with_ref_mut(self) -> Self {
1221 Self {
1222 display_ref_mut: true,
1223 ..self
1224 }
1225 }
1226
1227 pub const fn without_ref_mut(self) -> Self {
1228 Self {
1229 display_ref_mut: false,
1230 ..self
1231 }
1232 }
1233
1234 pub const fn with_param_names(self) -> Self {
1235 Self {
1236 display_param_names: true,
1237 ..self
1238 }
1239 }
1240
1241 pub const fn without_param_names(self) -> Self {
1242 Self {
1243 display_param_names: false,
1244 ..self
1245 }
1246 }
1247
1248 pub const fn with_param_types(self) -> Self {
1249 Self {
1250 display_param_types: true,
1251 ..self
1252 }
1253 }
1254
1255 pub const fn without_param_types(self) -> Self {
1256 Self {
1257 display_param_types: false,
1258 ..self
1259 }
1260 }
1261
1262 pub const fn with_return_type(self) -> Self {
1263 Self {
1264 display_return_type: true,
1265 ..self
1266 }
1267 }
1268
1269 pub const fn without_return_type(self) -> Self {
1270 Self {
1271 display_return_type: false,
1272 ..self
1273 }
1274 }
1275
1276 pub const fn with_types_display(self, types_display: TypeInfoDisplay) -> Self {
1277 Self {
1278 types_display,
1279 ..self
1280 }
1281 }
1282
1283 pub const fn with_signature(self) -> Self {
1284 Self {
1285 display_param_names: true,
1286 display_param_types: true,
1287 display_return_type: true,
1288 ..self
1289 }
1290 }
1291
1292 pub const fn without_signature(self) -> Self {
1293 Self {
1294 display_param_names: false,
1295 display_param_types: false,
1296 display_return_type: false,
1297 ..self
1298 }
1299 }
1300
1301 pub const fn with_parameters(self) -> Self {
1302 Self {
1303 display_param_names: true,
1304 display_param_types: true,
1305 ..self
1306 }
1307 }
1308
1309 pub const fn without_parameters(self) -> Self {
1310 Self {
1311 display_param_names: false,
1312 display_param_types: false,
1313 ..self
1314 }
1315 }
1316
1317 fn should_display_parameters(&self) -> bool {
1318 self.display_param_names || self.display_param_types
1319 }
1320
1321 fn should_display_param_type(&self, param: &TyFunctionParameter) -> bool {
1322 self.display_param_types
1323 && (param.is_self() && self.display_self_param_type || !param.is_self())
1324 }
1325
1326 fn is_module_function(&self, fn_decl: &TyFunctionDecl) -> bool {
1327 fn_decl.implementing_type.is_none() && fn_decl.implementing_for.is_none()
1328 }
1329
1330 fn calculate_initial_string_capacity(&self, fn_decl: &TyFunctionDecl) -> usize {
1333 const DEFAULT_TYPE_NAME_LENGTH: usize = 10;
1334 const DEFAULT_CONST_GENERIC_TYPE_PARAM_LENGTH: usize = 2; const DOUBLE_COLON_LENGTH: usize = 2;
1336
1337 let mut capacity = 0;
1338
1339 if (self.display_trait || self.display_self_type) && fn_decl.implementing_type.is_some() {
1340 capacity += DEFAULT_TYPE_NAME_LENGTH + DOUBLE_COLON_LENGTH;
1341 }
1342
1343 capacity += fn_decl.name.as_str().len();
1344 if self.display_module_fn_call_path && self.is_module_function(fn_decl) {
1346 capacity += fn_decl.call_path.prefixes.iter().fold(0, |acc, prefix| {
1347 acc + prefix.as_str().len() + DOUBLE_COLON_LENGTH
1348 });
1349 }
1350
1351 if self.display_fn_type_params && !fn_decl.type_parameters.is_empty() {
1352 capacity += 2; capacity += fn_decl.type_parameters.iter().fold(0, |acc, tp| {
1354 acc + match tp {
1355 TypeParameter::Type(_) => DEFAULT_TYPE_NAME_LENGTH,
1356 TypeParameter::Const(_) => DEFAULT_CONST_GENERIC_TYPE_PARAM_LENGTH,
1357 } + 2 });
1359 }
1360
1361 if self.should_display_parameters() {
1362 capacity += 2; fn_decl.parameters.iter().for_each(|param| {
1365 if self.display_param_names {
1366 capacity += param.name.as_str().len();
1367 if self.should_display_param_type(param) {
1368 capacity += 2; }
1370 }
1371 if self.should_display_param_type(param) {
1372 capacity += DEFAULT_TYPE_NAME_LENGTH;
1373 }
1374
1375 capacity += 2; });
1377
1378 if !fn_decl.parameters.is_empty() {
1379 capacity -= 2; }
1381 }
1382
1383 if self.display_return_type {
1384 capacity += 4; capacity += DEFAULT_TYPE_NAME_LENGTH;
1386 }
1387
1388 capacity
1389 }
1390
1391 pub fn display(&self, fn_decl: &TyFunctionDecl, engines: &Engines) -> String {
1392 let mut result = String::with_capacity(self.calculate_initial_string_capacity(fn_decl));
1393
1394 if self.display_module_fn_call_path && self.is_module_function(fn_decl) {
1397 if let Some((first_prefix, rest_prefixes)) = fn_decl.call_path.prefixes.split_first() {
1400 let first_prefix = if !first_prefix.as_str().contains('-') {
1401 first_prefix.as_str()
1402 } else {
1403 &first_prefix.as_str().replace('-', "_")
1404 };
1405 result.push_str(first_prefix);
1406 result.push_str("::");
1407 for prefix in rest_prefixes {
1408 result.push_str(prefix.as_str());
1409 result.push_str("::");
1410 }
1411 }
1412
1413 } else if self.display_self_type || self.display_trait {
1418 match fn_decl.implementing_type.as_ref() {
1419 Some(TyDecl::TraitDecl(trait_decl)) if self.display_self_type => {
1420 let trait_decl = engines.de().get_trait(&trait_decl.decl_id);
1423 self.display_udt_decl_into(
1424 &trait_decl.call_path,
1425 Either::Left(&trait_decl.type_parameters),
1426 engines,
1427 &mut result,
1428 );
1429 result.push_str("::");
1430 }
1431 Some(TyDecl::AbiDecl(abi_decl)) if self.display_self_type => {
1432 let abi_decl = engines.de().get_abi(&abi_decl.decl_id);
1435 result.push_str(abi_decl.name.as_str());
1438 result.push_str("::");
1439 }
1440 Some(TyDecl::ImplSelfOrTrait(impl_self_or_trait_decl)) => {
1441 let impl_self_or_trait_decl = engines
1442 .de()
1443 .get_impl_self_or_trait(&impl_self_or_trait_decl.decl_id);
1444 let self_type = if self.display_self_type {
1445 let implementing_for = match fn_decl.implementing_for {
1446 Some(implementing_for) => engines.te().get(implementing_for),
1447 None => {
1448 engines
1451 .te()
1452 .get(impl_self_or_trait_decl.implementing_for.type_id)
1453 }
1454 };
1455 Some(
1456 self.types_display
1457 .display(&implementing_for, engines)
1458 .to_string(),
1459 )
1460 } else {
1461 None
1462 };
1463 let trait_type = if self.display_trait {
1464 impl_self_or_trait_decl
1465 .as_ref()
1466 .trait_decl_ref
1467 .as_ref()
1468 .map(|trait_or_abi_decl| {
1469 match trait_or_abi_decl.id() {
1470 InterfaceDeclId::Abi(decl_id) => {
1471 let abi_decl = engines.de().get_abi(decl_id);
1472 abi_decl.name.to_string()
1473 }
1474 InterfaceDeclId::Trait(decl_id) => {
1475 let trait_decl = engines.de().get_trait(decl_id);
1476 self.display_udt_decl(
1479 &trait_decl.call_path,
1480 Either::Right(
1481 &impl_self_or_trait_decl.trait_type_arguments,
1482 ),
1483 engines,
1484 )
1485 }
1486 }
1487 })
1488 } else {
1489 None
1490 };
1491
1492 match (self_type, trait_type) {
1493 (None, None) => {}
1494 (None, Some(type_name)) | (Some(type_name), None) => {
1495 result.push_str(&type_name);
1496 result.push_str("::");
1497 }
1498 (Some(self_type), Some(trait_type)) => {
1499 result.push('<');
1500 result.push_str(&self_type);
1501 result.push_str(" as ");
1502 result.push_str(&trait_type);
1503 result.push('>');
1504 result.push_str("::");
1505 }
1506 }
1507 }
1508 _ => {
1509 if let Some(implementing_for) = fn_decl.implementing_for {
1510 let implementing_for = engines.te().get(implementing_for);
1511 result.push_str(&self.types_display.display(&implementing_for, engines));
1512 result.push_str("::");
1513 }
1514 }
1515 }
1516 }
1517
1518 result.push_str(fn_decl.name.as_str());
1520
1521 if self.should_display_parameters() {
1523 result.push('(');
1524
1525 fn_decl.parameters.iter().for_each(|param| {
1526 if self.display_ref_mut && param.is_mutable && param.is_reference {
1527 result.push_str("ref mut ");
1528 }
1529 if self.display_param_names {
1530 result.push_str(param.name.as_str());
1531 if self.should_display_param_type(param) {
1532 result.push_str(": ");
1533 }
1534 }
1535 if self.should_display_param_type(param) {
1536 let param_type = engines.te().get(param.type_argument.type_id);
1537 result.push_str(&self.types_display.display(¶m_type, engines));
1538 }
1539
1540 result.push_str(", ");
1541 });
1542
1543 result.truncate(result.rfind(',').unwrap_or(result.len()));
1545
1546 result.push(')');
1547 }
1548
1549 if self.display_return_type {
1551 result.push_str(" -> ");
1552 let return_type = engines.te().get(fn_decl.return_type.type_id);
1553 result.push_str(&self.types_display.display(&return_type, engines));
1554 }
1555
1556 result
1557 }
1558
1559 fn display_udt_decl(
1560 &self,
1561 udt_name: &CallPath,
1562 type_params: Either<&[TypeParameter], &[GenericArgument]>,
1563 engines: &Engines,
1564 ) -> String {
1565 let capacity = udt_name.suffix.as_str().len()
1566 + if self.types_display.display_call_paths {
1567 udt_name
1568 .prefixes
1569 .iter()
1570 .map(|p| p.as_str().len())
1571 .sum::<usize>()
1572 } else {
1573 0
1574 };
1575
1576 let mut dest = String::with_capacity(capacity);
1577 self.display_udt_decl_into(udt_name, type_params, engines, &mut dest);
1578 dest
1579 }
1580
1581 fn display_udt_decl_into(
1584 &self,
1585 udt_name: &CallPath,
1586 type_params: Either<&[TypeParameter], &[GenericArgument]>,
1587 engines: &Engines,
1588 dest: &mut String,
1589 ) {
1590 if self.types_display.display_call_paths {
1591 dest.push_str(&udt_name.to_string());
1592 } else {
1593 dest.push_str(udt_name.suffix.as_str());
1594 }
1595
1596 match type_params {
1597 Either::Left(type_params) => {
1598 if !type_params.is_empty() {
1599 dest.push_str(
1600 &self
1601 .types_display
1602 .display_non_empty_type_params(type_params, engines),
1603 );
1604 }
1605 }
1606 Either::Right(generic_args) => {
1607 if !generic_args.is_empty() {
1608 dest.push_str(
1609 &self
1610 .types_display
1611 .display_non_empty_generic_args(generic_args, engines),
1612 );
1613 }
1614 }
1615 }
1616 }
1617}