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_modified(method.clone(), *self.id())
445 .with_parent(decl_engine, self.id().into())
446 } else {
447 self.clone()
448 };
449
450 engines.obs().trace(|| {
451 format!(
452 " after get_method_safe_to_unify: {:?}; {:?}",
453 engines.help_out(type_id),
454 engines.help_out(decl_ref.id())
455 )
456 });
457
458 return decl_ref;
459 }
460
461 engines.obs().trace(|| {
462 format!(
463 " after get_method_safe_to_unify: {:?}; {:?}",
464 engines.help_out(type_id),
465 engines.help_out(self.id())
466 )
467 });
468
469 self.clone()
470 }
471}
472
473impl Named for TyFunctionDecl {
474 fn name(&self) -> &Ident {
475 &self.name
476 }
477}
478
479impl IsConcrete for TyFunctionDecl {
480 fn is_concrete(&self, handler: &Handler, engines: &Engines) -> bool {
481 self.type_parameters
482 .iter()
483 .all(|tp| tp.is_concrete(handler, engines))
484 && self
485 .return_type
486 .type_id
487 .is_concrete(engines, TreatNumericAs::Concrete)
488 && self.parameters().iter().all(|t| {
489 t.type_argument
490 .type_id
491 .is_concrete(engines, TreatNumericAs::Concrete)
492 })
493 }
494}
495impl declaration::FunctionSignature for TyFunctionDecl {
496 fn parameters(&self) -> &Vec<TyFunctionParameter> {
497 &self.parameters
498 }
499
500 fn return_type(&self) -> &GenericTypeArgument {
501 &self.return_type
502 }
503}
504
505impl EqWithEngines for TyFunctionDecl {}
506impl PartialEqWithEngines for TyFunctionDecl {
507 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
508 self.name == other.name
509 && self.body.eq(&other.body, ctx)
510 && self.parameters.eq(&other.parameters, ctx)
511 && self.return_type.eq(&other.return_type, ctx)
512 && self.type_parameters.eq(&other.type_parameters, ctx)
513 && self.visibility == other.visibility
514 && self.is_contract_call == other.is_contract_call
515 && self.purity == other.purity
516 && self.call_path == other.call_path
517 && self.span == other.span
518 }
519}
520
521impl HashWithEngines for TyFunctionDecl {
522 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
523 let TyFunctionDecl {
524 name,
525 body,
526 parameters,
527 return_type,
528 type_parameters,
529 visibility,
530 is_contract_call,
531 purity,
532 call_path,
533 span,
534 attributes: _,
537 implementing_type: _,
538 implementing_for: _,
539 where_clause: _,
540 is_trait_method_dummy: _,
541 is_type_check_finalized: _,
542 kind: _,
543 } = self;
544 name.hash(state);
545 body.hash(state, engines);
546 parameters.hash(state, engines);
547 return_type.hash(state, engines);
548 type_parameters.hash(state, engines);
549 visibility.hash(state);
550 is_contract_call.hash(state);
551 purity.hash(state);
552 call_path.hash(state);
553 span.hash(state);
554 }
555}
556
557impl SubstTypes for TyFunctionDecl {
558 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
559 let mut has_changes = if ctx.subst_function_body {
560 has_changes! {
561 self.type_parameters.subst(ctx);
562 self.parameters.subst(ctx);
563 self.return_type.subst(ctx);
564 self.body.subst(ctx);
565 self.implementing_for.subst(ctx);
566 }
567 } else {
568 has_changes! {
569 self.type_parameters.subst(ctx);
570 self.parameters.subst(ctx);
571 self.return_type.subst(ctx);
572 self.implementing_for.subst(ctx);
573 }
574 };
575
576 if let Some(map) = ctx.type_subst_map.as_ref() {
577 let handler = Handler::default();
578 for (name, value) in &map.const_generics_materialization {
579 if let Ok(materialization_has_changes) =
580 self.materialize_const_generics(ctx.engines, &handler, name, value)
581 {
582 has_changes |= materialization_has_changes;
583 }
584 }
585 }
586
587 has_changes
588 }
589}
590
591impl ReplaceDecls for TyFunctionDecl {
592 fn replace_decls_inner(
593 &mut self,
594 decl_mapping: &DeclMapping,
595 handler: &Handler,
596 ctx: &mut TypeCheckContext,
597 ) -> Result<HasChanges, ErrorEmitted> {
598 let mut func_ctx = ctx.by_ref().with_self_type(self.implementing_for);
599 self.body
600 .replace_decls(decl_mapping, handler, &mut func_ctx)
601 }
602}
603
604impl Spanned for TyFunctionDecl {
605 fn span(&self) -> Span {
606 self.span.clone()
607 }
608}
609
610impl MonomorphizeHelper for TyFunctionDecl {
611 fn type_parameters(&self) -> &[TypeParameter] {
612 &self.type_parameters
613 }
614
615 fn name(&self) -> &Ident {
616 &self.name
617 }
618
619 fn has_self_type_param(&self) -> bool {
620 false
621 }
622}
623
624impl CollectTypesMetadata for TyFunctionDecl {
625 fn collect_types_metadata(
626 &self,
627 handler: &Handler,
628 ctx: &mut CollectTypesMetadataContext,
629 ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
630 let mut body = vec![];
631 for content in self.body.contents.iter() {
632 body.append(&mut content.collect_types_metadata(handler, ctx)?);
633 }
634 body.append(
635 &mut self
636 .return_type
637 .type_id
638 .collect_types_metadata(handler, ctx)?,
639 );
640 for p in self.type_parameters.iter() {
641 let p = p
642 .as_type_parameter()
643 .expect("only works for type parameters");
644 body.append(&mut p.type_id.collect_types_metadata(handler, ctx)?);
645 }
646 for param in self.parameters.iter() {
647 body.append(
648 &mut param
649 .type_argument
650 .type_id
651 .collect_types_metadata(handler, ctx)?,
652 );
653 }
654 Ok(body)
655 }
656}
657
658impl TyFunctionDecl {
659 pub(crate) fn set_implementing_type(&mut self, decl: TyDecl) {
660 self.implementing_type = Some(decl);
661 }
662
663 pub(crate) fn error(decl: &parsed::FunctionDeclaration) -> TyFunctionDecl {
666 let parsed::FunctionDeclaration {
667 name,
668 return_type,
669 span,
670 visibility,
671 purity,
672 where_clause,
673 kind,
674 ..
675 } = decl;
676 TyFunctionDecl {
677 purity: *purity,
678 name: name.clone(),
679 body: <_>::default(),
680 implementing_type: None,
681 implementing_for: None,
682 span: span.clone(),
683 call_path: CallPath::from(Ident::dummy()),
684 attributes: Default::default(),
685 is_contract_call: false,
686 parameters: Default::default(),
687 visibility: *visibility,
688 return_type: return_type.clone(),
689 type_parameters: Default::default(),
690 where_clause: where_clause.clone(),
691 is_trait_method_dummy: false,
692 is_type_check_finalized: true,
693 kind: match kind {
694 FunctionDeclarationKind::Default => TyFunctionDeclKind::Default,
695 FunctionDeclarationKind::Entry => TyFunctionDeclKind::Entry,
696 FunctionDeclarationKind::Test => TyFunctionDeclKind::Test,
697 FunctionDeclarationKind::Main => TyFunctionDeclKind::Main,
698 },
699 }
700 }
701
702 pub(crate) fn parameters_span(&self) -> Span {
704 if !self.parameters.is_empty() {
705 self.parameters.iter().fold(
706 self.parameters[0].name.span(),
708 |acc, TyFunctionParameter { type_argument, .. }| {
709 Span::join(acc, &type_argument.span)
710 },
711 )
712 } else {
713 self.name.span()
714 }
715 }
716
717 pub fn to_fn_selector_value_untruncated(
718 &self,
719 handler: &Handler,
720 engines: &Engines,
721 ) -> Result<Vec<u8>, ErrorEmitted> {
722 let mut hasher = Sha256::new();
723 let data = self.to_selector_name(handler, engines)?;
724 hasher.update(data);
725 let hash = hasher.finalize();
726 Ok(hash.to_vec())
727 }
728
729 pub fn to_fn_selector_value(
733 &self,
734 handler: &Handler,
735 engines: &Engines,
736 ) -> Result<[u8; 4], ErrorEmitted> {
737 let hash = self.to_fn_selector_value_untruncated(handler, engines)?;
738 let mut buf = [0u8; 4];
740 buf.copy_from_slice(&hash[..4]);
741 Ok(buf)
742 }
743
744 pub fn to_selector_name(
745 &self,
746 handler: &Handler,
747 engines: &Engines,
748 ) -> Result<String, ErrorEmitted> {
749 let named_params = self
750 .parameters
751 .iter()
752 .map(|TyFunctionParameter { type_argument, .. }| {
753 engines
754 .te()
755 .to_typeinfo(type_argument.type_id, &type_argument.span)
756 .expect("unreachable I think?")
757 .to_selector_name(handler, engines, &type_argument.span)
758 })
759 .filter_map(|name| name.ok())
760 .collect::<Vec<String>>();
761
762 Ok(format!(
763 "{}({})",
764 self.name.as_str(),
765 named_params.join(","),
766 ))
767 }
768
769 pub fn is_default(&self) -> bool {
770 !(self.is_entry() || self.is_main() || self.is_test())
773 }
774
775 pub fn is_entry(&self) -> bool {
777 matches!(self.kind, TyFunctionDeclKind::Entry)
778 }
779
780 pub fn is_main(&self) -> bool {
781 matches!(self.kind, TyFunctionDeclKind::Main)
782 }
783
784 pub fn is_test(&self) -> bool {
786 self.attributes.has_any_of_kind(AttributeKind::Test)
789 }
790
791 pub fn inline(&self) -> Option<Inline> {
792 self.attributes.inline()
793 }
794
795 pub fn trace(&self) -> Option<Trace> {
796 self.attributes.trace()
797 }
798
799 pub fn is_fallback(&self) -> bool {
800 self.attributes.has_any_of_kind(AttributeKind::Fallback)
801 }
802
803 pub fn is_constructor(&self, engines: &Engines, type_id: TypeId) -> Option<bool> {
808 if self
809 .parameters
810 .first()
811 .map(|param| param.is_self())
812 .unwrap_or_default()
813 {
814 return Some(false);
815 };
816
817 match &self.implementing_type {
818 Some(TyDecl::ImplSelfOrTrait(t)) => {
819 let unify_check = UnifyCheck::non_dynamic_equality(engines);
820
821 let implementing_for = engines.de().get(&t.decl_id).implementing_for.type_id;
822
823 if unify_check.check(type_id, implementing_for)
829 && unify_check.check(type_id, self.return_type.type_id)
830 {
831 Some(true)
832 } else {
833 None
834 }
835 }
836 _ => Some(false),
837 }
838 }
839
840 pub fn is_from_blanket_impl(&self, engines: &Engines) -> bool {
841 if let Some(TyDecl::ImplSelfOrTrait(existing_impl_trait)) = &self.implementing_type {
842 let existing_trait_decl = engines
843 .de()
844 .get_impl_self_or_trait(&existing_impl_trait.decl_id);
845 if !existing_trait_decl.impl_type_parameters.is_empty()
846 && matches!(
847 *engines
848 .te()
849 .get(existing_trait_decl.implementing_for.type_id),
850 TypeInfo::UnknownGeneric { .. }
851 )
852 {
853 return true;
854 }
855 }
856 false
857 }
858}
859
860#[derive(Debug, Clone, Serialize, Deserialize)]
861pub struct TyFunctionParameter {
862 pub name: Ident,
863 pub is_reference: bool,
864 pub is_mutable: bool,
865 pub mutability_span: Span,
866 pub type_argument: GenericTypeArgument,
867}
868
869impl EqWithEngines for TyFunctionParameter {}
870impl PartialEqWithEngines for TyFunctionParameter {
871 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
872 self.name == other.name
873 && self.type_argument.eq(&other.type_argument, ctx)
874 && self.is_reference == other.is_reference
875 && self.is_mutable == other.is_mutable
876 }
877}
878
879impl HashWithEngines for TyFunctionParameter {
880 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
881 let TyFunctionParameter {
882 name,
883 is_reference,
884 is_mutable,
885 type_argument,
886 mutability_span: _,
889 } = self;
890 name.hash(state);
891 type_argument.hash(state, engines);
892 is_reference.hash(state);
893 is_mutable.hash(state);
894 }
895}
896
897impl SubstTypes for TyFunctionParameter {
898 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
899 self.type_argument.type_id.subst(ctx)
900 }
901}
902
903impl TyFunctionParameter {
904 pub fn is_self(&self) -> bool {
905 self.name.as_str() == "self"
906 }
907}
908
909#[derive(Clone, Debug, PartialEq, Eq, Hash)]
910pub enum TyFunctionSigTypeParameter {
911 Type(TypeId),
912 Const(ConstGenericExpr),
913}
914
915#[derive(Clone, Debug, PartialEq, Eq, Hash)]
916pub struct TyFunctionSig {
917 pub return_type: TypeId,
918 pub parameters: Vec<TypeId>,
919 pub type_parameters: Vec<TyFunctionSigTypeParameter>,
920}
921
922impl DisplayWithEngines for TyFunctionSig {
923 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
924 write!(f, "{:?}", engines.help_out(self))
925 }
926}
927
928impl DebugWithEngines for TyFunctionSig {
929 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
930 let tp_str = if self.type_parameters.is_empty() {
931 "".to_string()
932 } else {
933 format!(
934 "<{}>",
935 self.type_parameters
936 .iter()
937 .map(|p| match p {
938 TyFunctionSigTypeParameter::Type(t) => format!("{:?}", engines.help_out(t)),
939 TyFunctionSigTypeParameter::Const(expr) =>
940 format!("{:?}", engines.help_out(expr)),
941 })
942 .collect::<Vec<_>>()
943 .join(", "),
944 )
945 };
946 write!(
947 f,
948 "fn{}({}) -> {}",
949 tp_str,
950 self.parameters
951 .iter()
952 .map(|p| format!("{}", engines.help_out(p)))
953 .collect::<Vec<_>>()
954 .join(", "),
955 engines.help_out(self.return_type),
956 )
957 }
958}
959
960impl TyFunctionSig {
961 pub fn from_fn_decl(fn_decl: &TyFunctionDecl) -> Self {
962 Self {
963 return_type: fn_decl.return_type.type_id,
964 parameters: fn_decl
965 .parameters
966 .iter()
967 .map(|p| p.type_argument.type_id)
968 .collect::<Vec<_>>(),
969 type_parameters: fn_decl
970 .type_parameters
971 .iter()
972 .map(|x| match x {
973 TypeParameter::Type(p) => TyFunctionSigTypeParameter::Type(p.type_id),
974 TypeParameter::Const(p) => {
975 let expr = ConstGenericExpr::AmbiguousVariableExpression {
976 ident: p.name.clone(),
977 decl: None,
978 };
979 TyFunctionSigTypeParameter::Const(p.expr.clone().unwrap_or(expr))
980 }
981 })
982 .collect(),
983 }
984 }
985
986 pub fn is_concrete(&self, engines: &Engines) -> bool {
987 self.return_type
988 .is_concrete(engines, TreatNumericAs::Concrete)
989 && self
990 .parameters
991 .iter()
992 .all(|p| p.is_concrete(engines, TreatNumericAs::Concrete))
993 && self.type_parameters.iter().all(|x| match x {
994 TyFunctionSigTypeParameter::Type(type_id) => {
995 type_id.is_concrete(engines, TreatNumericAs::Concrete)
996 }
997 TyFunctionSigTypeParameter::Const(expr) => match expr {
998 ConstGenericExpr::Literal { .. } => true,
999 ConstGenericExpr::AmbiguousVariableExpression { .. } => false,
1000 },
1001 })
1002 }
1003
1004 pub fn get_type_str(&self, engines: &Engines) -> String {
1008 let tp_str = if self.type_parameters.is_empty() {
1009 "".to_string()
1010 } else {
1011 format!(
1012 "<{}>",
1013 self.type_parameters
1014 .iter()
1015 .map(|x| match x {
1016 TyFunctionSigTypeParameter::Type(type_id) => type_id.get_type_str(engines),
1017 TyFunctionSigTypeParameter::Const(p) => {
1018 match p {
1019 ConstGenericExpr::Literal { val, .. } => val.to_string(),
1020 ConstGenericExpr::AmbiguousVariableExpression { ident, .. } => {
1021 ident.as_str().to_string()
1022 }
1023 }
1024 }
1025 })
1026 .collect::<Vec<_>>()
1027 .join(", "),
1028 )
1029 };
1030 format!(
1031 "fn{}({}) -> {}",
1032 tp_str,
1033 self.parameters
1034 .iter()
1035 .map(|p| p.get_type_str(engines))
1036 .collect::<Vec<_>>()
1037 .join(", "),
1038 self.return_type.get_type_str(engines),
1039 )
1040 }
1041}
1042
1043#[derive(Debug, Clone, Copy)]
1073pub struct TyFunctionDisplay {
1074 display_self_type: bool,
1081 display_trait: bool,
1084 display_module_fn_call_path: bool,
1087 display_fn_type_params: bool,
1090 display_self_param_type: bool,
1095 display_ref_mut: bool,
1098 display_param_names: bool,
1101 display_param_types: bool,
1104 display_return_type: bool,
1107 types_display: TypeInfoDisplay,
1114}
1115
1116impl TyFunctionDisplay {
1117 pub const fn only_name() -> Self {
1118 Self {
1119 display_trait: false,
1120 display_self_type: false,
1121 display_module_fn_call_path: false,
1122 display_fn_type_params: false,
1123 display_self_param_type: false,
1124 display_ref_mut: false,
1125 display_param_names: false,
1126 display_param_types: false,
1127 display_return_type: false,
1128 types_display: TypeInfoDisplay::only_name(),
1129 }
1130 }
1131
1132 pub const fn full() -> Self {
1133 Self {
1134 display_trait: true,
1135 display_self_type: true,
1136 display_module_fn_call_path: true,
1137 display_fn_type_params: true,
1138 display_self_param_type: true,
1139 display_ref_mut: true,
1140 display_param_names: true,
1141 display_param_types: true,
1142 display_return_type: true,
1143 types_display: TypeInfoDisplay::full(),
1144 }
1145 }
1146
1147 pub const fn with_trait(self) -> Self {
1148 Self {
1149 display_trait: true,
1150 ..self
1151 }
1152 }
1153
1154 pub const fn without_trait(self) -> Self {
1155 Self {
1156 display_trait: false,
1157 ..self
1158 }
1159 }
1160
1161 pub const fn with_self_type(self) -> Self {
1162 Self {
1163 display_self_type: true,
1164 ..self
1165 }
1166 }
1167
1168 pub const fn without_self_type(self) -> Self {
1169 Self {
1170 display_self_type: false,
1171 ..self
1172 }
1173 }
1174
1175 pub const fn with_module_fn_call_path(self) -> Self {
1176 Self {
1177 display_module_fn_call_path: true,
1178 ..self
1179 }
1180 }
1181
1182 pub const fn without_module_fn_call_path(self) -> Self {
1183 Self {
1184 display_module_fn_call_path: false,
1185 ..self
1186 }
1187 }
1188
1189 pub const fn with_fn_type_params(self) -> Self {
1190 Self {
1191 display_fn_type_params: true,
1192 ..self
1193 }
1194 }
1195
1196 pub const fn without_fn_type_params(self) -> Self {
1197 Self {
1198 display_fn_type_params: false,
1199 ..self
1200 }
1201 }
1202
1203 pub const fn with_self_param_type(self) -> Self {
1204 Self {
1205 display_self_param_type: true,
1206 ..self
1207 }
1208 }
1209
1210 pub const fn without_self_param_type(self) -> Self {
1211 Self {
1212 display_self_param_type: false,
1213 ..self
1214 }
1215 }
1216
1217 pub const fn with_ref_mut(self) -> Self {
1218 Self {
1219 display_ref_mut: true,
1220 ..self
1221 }
1222 }
1223
1224 pub const fn without_ref_mut(self) -> Self {
1225 Self {
1226 display_ref_mut: false,
1227 ..self
1228 }
1229 }
1230
1231 pub const fn with_param_names(self) -> Self {
1232 Self {
1233 display_param_names: true,
1234 ..self
1235 }
1236 }
1237
1238 pub const fn without_param_names(self) -> Self {
1239 Self {
1240 display_param_names: false,
1241 ..self
1242 }
1243 }
1244
1245 pub const fn with_param_types(self) -> Self {
1246 Self {
1247 display_param_types: true,
1248 ..self
1249 }
1250 }
1251
1252 pub const fn without_param_types(self) -> Self {
1253 Self {
1254 display_param_types: false,
1255 ..self
1256 }
1257 }
1258
1259 pub const fn with_return_type(self) -> Self {
1260 Self {
1261 display_return_type: true,
1262 ..self
1263 }
1264 }
1265
1266 pub const fn without_return_type(self) -> Self {
1267 Self {
1268 display_return_type: false,
1269 ..self
1270 }
1271 }
1272
1273 pub const fn with_types_display(self, types_display: TypeInfoDisplay) -> Self {
1274 Self {
1275 types_display,
1276 ..self
1277 }
1278 }
1279
1280 pub const fn with_signature(self) -> Self {
1281 Self {
1282 display_param_names: true,
1283 display_param_types: true,
1284 display_return_type: true,
1285 ..self
1286 }
1287 }
1288
1289 pub const fn without_signature(self) -> Self {
1290 Self {
1291 display_param_names: false,
1292 display_param_types: false,
1293 display_return_type: false,
1294 ..self
1295 }
1296 }
1297
1298 pub const fn with_parameters(self) -> Self {
1299 Self {
1300 display_param_names: true,
1301 display_param_types: true,
1302 ..self
1303 }
1304 }
1305
1306 pub const fn without_parameters(self) -> Self {
1307 Self {
1308 display_param_names: false,
1309 display_param_types: false,
1310 ..self
1311 }
1312 }
1313
1314 fn should_display_parameters(&self) -> bool {
1315 self.display_param_names || self.display_param_types
1316 }
1317
1318 fn should_display_param_type(&self, param: &TyFunctionParameter) -> bool {
1319 self.display_param_types
1320 && (param.is_self() && self.display_self_param_type || !param.is_self())
1321 }
1322
1323 fn is_module_function(&self, fn_decl: &TyFunctionDecl) -> bool {
1324 fn_decl.implementing_type.is_none() && fn_decl.implementing_for.is_none()
1325 }
1326
1327 fn calculate_initial_string_capacity(&self, fn_decl: &TyFunctionDecl) -> usize {
1330 const DEFAULT_TYPE_NAME_LENGTH: usize = 10;
1331 const DEFAULT_CONST_GENERIC_TYPE_PARAM_LENGTH: usize = 2; const DOUBLE_COLON_LENGTH: usize = 2;
1333
1334 let mut capacity = 0;
1335
1336 if (self.display_trait || self.display_self_type) && fn_decl.implementing_type.is_some() {
1337 capacity += DEFAULT_TYPE_NAME_LENGTH + DOUBLE_COLON_LENGTH;
1338 }
1339
1340 capacity += fn_decl.name.as_str().len();
1341 if self.display_module_fn_call_path && self.is_module_function(fn_decl) {
1343 capacity += fn_decl.call_path.prefixes.iter().fold(0, |acc, prefix| {
1344 acc + prefix.as_str().len() + DOUBLE_COLON_LENGTH
1345 });
1346 }
1347
1348 if self.display_fn_type_params && !fn_decl.type_parameters.is_empty() {
1349 capacity += 2; capacity += fn_decl.type_parameters.iter().fold(0, |acc, tp| {
1351 acc + match tp {
1352 TypeParameter::Type(_) => DEFAULT_TYPE_NAME_LENGTH,
1353 TypeParameter::Const(_) => DEFAULT_CONST_GENERIC_TYPE_PARAM_LENGTH,
1354 } + 2 });
1356 }
1357
1358 if self.should_display_parameters() {
1359 capacity += 2; fn_decl.parameters.iter().for_each(|param| {
1362 if self.display_param_names {
1363 capacity += param.name.as_str().len();
1364 if self.should_display_param_type(param) {
1365 capacity += 2; }
1367 }
1368 if self.should_display_param_type(param) {
1369 capacity += DEFAULT_TYPE_NAME_LENGTH;
1370 }
1371
1372 capacity += 2; });
1374
1375 if !fn_decl.parameters.is_empty() {
1376 capacity -= 2; }
1378 }
1379
1380 if self.display_return_type {
1381 capacity += 4; capacity += DEFAULT_TYPE_NAME_LENGTH;
1383 }
1384
1385 capacity
1386 }
1387
1388 pub fn display(&self, fn_decl: &TyFunctionDecl, engines: &Engines) -> String {
1389 let mut result = String::with_capacity(self.calculate_initial_string_capacity(fn_decl));
1390
1391 if self.display_module_fn_call_path && self.is_module_function(fn_decl) {
1394 if let Some((first_prefix, rest_prefixes)) = fn_decl.call_path.prefixes.split_first() {
1397 let first_prefix = if !first_prefix.as_str().contains('-') {
1398 first_prefix.as_str()
1399 } else {
1400 &first_prefix.as_str().replace('-', "_")
1401 };
1402 result.push_str(first_prefix);
1403 result.push_str("::");
1404 for prefix in rest_prefixes {
1405 result.push_str(prefix.as_str());
1406 result.push_str("::");
1407 }
1408 }
1409
1410 } else if self.display_self_type || self.display_trait {
1415 match fn_decl.implementing_type.as_ref() {
1416 Some(TyDecl::TraitDecl(trait_decl)) if self.display_self_type => {
1417 let trait_decl = engines.de().get_trait(&trait_decl.decl_id);
1420 self.display_udt_decl_into(
1421 &trait_decl.call_path,
1422 Either::Left(&trait_decl.type_parameters),
1423 engines,
1424 &mut result,
1425 );
1426 result.push_str("::");
1427 }
1428 Some(TyDecl::AbiDecl(abi_decl)) if self.display_self_type => {
1429 let abi_decl = engines.de().get_abi(&abi_decl.decl_id);
1432 result.push_str(abi_decl.name.as_str());
1435 result.push_str("::");
1436 }
1437 Some(TyDecl::ImplSelfOrTrait(impl_self_or_trait_decl)) => {
1438 let impl_self_or_trait_decl = engines
1439 .de()
1440 .get_impl_self_or_trait(&impl_self_or_trait_decl.decl_id);
1441 let self_type = if self.display_self_type {
1442 let implementing_for = match fn_decl.implementing_for {
1443 Some(implementing_for) => engines.te().get(implementing_for),
1444 None => {
1445 engines
1448 .te()
1449 .get(impl_self_or_trait_decl.implementing_for.type_id)
1450 }
1451 };
1452 Some(
1453 self.types_display
1454 .display(&implementing_for, engines)
1455 .to_string(),
1456 )
1457 } else {
1458 None
1459 };
1460 let trait_type = if self.display_trait {
1461 impl_self_or_trait_decl
1462 .as_ref()
1463 .trait_decl_ref
1464 .as_ref()
1465 .map(|trait_or_abi_decl| {
1466 match trait_or_abi_decl.id() {
1467 InterfaceDeclId::Abi(decl_id) => {
1468 let abi_decl = engines.de().get_abi(decl_id);
1469 abi_decl.name.to_string()
1470 }
1471 InterfaceDeclId::Trait(decl_id) => {
1472 let trait_decl = engines.de().get_trait(decl_id);
1473 self.display_udt_decl(
1476 &trait_decl.call_path,
1477 Either::Right(
1478 &impl_self_or_trait_decl.trait_type_arguments,
1479 ),
1480 engines,
1481 )
1482 }
1483 }
1484 })
1485 } else {
1486 None
1487 };
1488
1489 match (self_type, trait_type) {
1490 (None, None) => {}
1491 (None, Some(type_name)) | (Some(type_name), None) => {
1492 result.push_str(&type_name);
1493 result.push_str("::");
1494 }
1495 (Some(self_type), Some(trait_type)) => {
1496 result.push('<');
1497 result.push_str(&self_type);
1498 result.push_str(" as ");
1499 result.push_str(&trait_type);
1500 result.push('>');
1501 result.push_str("::");
1502 }
1503 }
1504 }
1505 _ => {
1506 if let Some(implementing_for) = fn_decl.implementing_for {
1507 let implementing_for = engines.te().get(implementing_for);
1508 result.push_str(&self.types_display.display(&implementing_for, engines));
1509 result.push_str("::");
1510 }
1511 }
1512 }
1513 }
1514
1515 result.push_str(fn_decl.name.as_str());
1517
1518 if self.should_display_parameters() {
1520 result.push('(');
1521
1522 fn_decl.parameters.iter().for_each(|param| {
1523 if self.display_ref_mut && param.is_mutable && param.is_reference {
1524 result.push_str("ref mut ");
1525 }
1526 if self.display_param_names {
1527 result.push_str(param.name.as_str());
1528 if self.should_display_param_type(param) {
1529 result.push_str(": ");
1530 }
1531 }
1532 if self.should_display_param_type(param) {
1533 let param_type = engines.te().get(param.type_argument.type_id);
1534 result.push_str(&self.types_display.display(¶m_type, engines));
1535 }
1536
1537 result.push_str(", ");
1538 });
1539
1540 result.truncate(result.rfind(',').unwrap_or(result.len()));
1542
1543 result.push(')');
1544 }
1545
1546 if self.display_return_type {
1548 result.push_str(" -> ");
1549 let return_type = engines.te().get(fn_decl.return_type.type_id);
1550 result.push_str(&self.types_display.display(&return_type, engines));
1551 }
1552
1553 result
1554 }
1555
1556 fn display_udt_decl(
1557 &self,
1558 udt_name: &CallPath,
1559 type_params: Either<&[TypeParameter], &[GenericArgument]>,
1560 engines: &Engines,
1561 ) -> String {
1562 let capacity = udt_name.suffix.as_str().len()
1563 + if self.types_display.display_call_paths {
1564 udt_name
1565 .prefixes
1566 .iter()
1567 .map(|p| p.as_str().len())
1568 .sum::<usize>()
1569 } else {
1570 0
1571 };
1572
1573 let mut dest = String::with_capacity(capacity);
1574 self.display_udt_decl_into(udt_name, type_params, engines, &mut dest);
1575 dest
1576 }
1577
1578 fn display_udt_decl_into(
1581 &self,
1582 udt_name: &CallPath,
1583 type_params: Either<&[TypeParameter], &[GenericArgument]>,
1584 engines: &Engines,
1585 dest: &mut String,
1586 ) {
1587 if self.types_display.display_call_paths {
1588 dest.push_str(&udt_name.to_string());
1589 } else {
1590 dest.push_str(udt_name.suffix.as_str());
1591 }
1592
1593 match type_params {
1594 Either::Left(type_params) => {
1595 if !type_params.is_empty() {
1596 dest.push_str(
1597 &self
1598 .types_display
1599 .display_non_empty_type_params(type_params, engines),
1600 );
1601 }
1602 }
1603 Either::Right(generic_args) => {
1604 if !generic_args.is_empty() {
1605 dest.push_str(
1606 &self
1607 .types_display
1608 .display_non_empty_generic_args(generic_args, engines),
1609 );
1610 }
1611 }
1612 }
1613 }
1614}