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