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