Concrete declarations keep generic types out of semantic analysis and IR.
(program: &Program)
| 12 | kind: &'static str, |
| 13 | generics: Vec<String>, |
| 14 | bounds: Vec<(String, crate::ast::Path)>, |
| 15 | alias_target: Option<Type>, |
| 16 | } |
| 17 | |
| 18 | type DeclarationBoundTemplates = HashMap<String, DeclarationBoundTemplate>; |
| 19 | |
| 20 | // Upper bound on distinct function specializations; exceeding it means a generic |
| 21 | // recurses at an unbounded type sequence. Real programs stay far below this. |
| 22 | const SPECIALIZATION_LIMIT: usize = 2048; |
| 23 | |
| 24 | // Concrete declarations keep generic types out of semantic analysis and IR. |
| 25 | pub(crate) fn monomorphize_program( |
| 26 | program: &Program, |
| 27 | associated: &crate::associated::AssociatedCatalog, |
| 28 | ) -> Result<Program, String> { |
| 29 | let mut source = program.clone(); |
| 30 | infer_implicit_type_arguments(&mut source)?; |
| 31 | |
| 32 | let definitions = source |
| 33 | .declarations |
| 34 | .iter() |
| 35 | .filter_map(|declaration| match &declaration.decl { |
| 36 | DeclNode::Function { name, generics, .. } if !generics.is_empty() => { |
| 37 | Some((name.clone(), declaration.clone())) |
| 38 | } |
| 39 | _ => None, |
| 40 | }) |
| 41 | .collect::<HashMap<_, _>>(); |
| 42 | |
| 43 | // Interface contracts and the concrete function pool for generic-bound checks. |
| 44 | let interfaces = source |
| 45 | .declarations |
| 46 | .iter() |
| 47 | .filter_map(|declaration| match &declaration.decl { |
| 48 | DeclNode::Interface { name, methods } => Some((name.clone(), methods.clone())), |
| 49 | _ => None, |
| 50 | }) |
| 51 | .collect::<HashMap<_, _>>(); |
| 52 | let concrete_signatures = source |
| 53 | .declarations |
| 54 | .iter() |
| 55 | .filter_map(|declaration| match &declaration.decl { |
| 56 | DeclNode::Function { |
| 57 | name, |
| 58 | generics, |
| 59 | params, |
| 60 | return_type, |
| 61 | .. |
| 62 | } if generics.is_empty() => { |
| 63 | let params = params.iter().map(|p| p.ty.clone()).collect::<Vec<_>>(); |
| 64 | let ret = return_type |
| 65 | .as_ref() |
| 66 | .map(|ReturnType::Single(ty)| ty.clone()); |
| 67 | Some((name.clone(), (params, ret))) |
| 68 | } |
| 69 | _ => None, |
| 70 | }) |
| 71 | .collect::<HashMap<_, _>>(); |