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