(&mut self, module: &Module)
| 565 | } |
| 566 | |
| 567 | fn collect_generics(&mut self, module: &Module) { |
| 568 | // Process all defining instructions for globals (types, constants, |
| 569 | // and module-scoped variables), and functions' `OpFunction` instructions, |
| 570 | // but note that for `OpFunction`s only the signature is considered, |
| 571 | // actual inference based on bodies happens later, in `infer_function`. |
| 572 | let types_global_values_and_functions = module |
| 573 | .types_global_values |
| 574 | .iter() |
| 575 | .chain(module.functions.iter().filter_map(|f| f.def.as_ref())); |
| 576 | |
| 577 | let mut forward_declared_pointers = FxHashSet::default(); |
| 578 | for inst in types_global_values_and_functions { |
| 579 | let result_id = if inst.class.opcode == Op::TypeForwardPointer { |
| 580 | forward_declared_pointers.insert(inst.operands[0].unwrap_id_ref()); |
| 581 | inst.operands[0].unwrap_id_ref() |
| 582 | } else { |
| 583 | let result_id = inst.result_id.unwrap_or_else(|| { |
| 584 | unreachable!( |
| 585 | "Op{:?} is in `types_global_values` but not have a result ID", |
| 586 | inst.class.opcode |
| 587 | ); |
| 588 | }); |
| 589 | if forward_declared_pointers.remove(&result_id) { |
| 590 | // HACK(eddyb) this is a forward-declared pointer, pretend |
| 591 | // it's not "generic" at all to avoid breaking the rest of |
| 592 | // the logic - see module-level docs for how this should be |
| 593 | // handled in the future to support recursive data types. |
| 594 | assert_eq!(inst.class.opcode, Op::TypePointer); |
| 595 | continue; |
| 596 | } |
| 597 | result_id |
| 598 | }; |
| 599 | |
| 600 | // Record all integer `OpConstant`s (used for `IndexComposite`). |
| 601 | if inst.class.opcode == Op::Constant { |
| 602 | if let Operand::LiteralInt32(x) = inst.operands[0] { |
| 603 | self.int_consts.insert(result_id, x); |
| 604 | } |
| 605 | } |
| 606 | |
| 607 | // Instantiate `inst` in a fresh inference context, to determine |
| 608 | // how many parameters it needs, and how they might be constrained. |
| 609 | let (param_count, param_values, replacements) = { |
| 610 | let mut infer_cx = InferCx::new(self); |
| 611 | infer_cx.instantiate_instruction(inst, InstructionLocation::Module); |
| 612 | |
| 613 | let param_count = infer_cx.infer_var_values.len() as u32; |
| 614 | |
| 615 | // FIXME(eddyb) dedup this with `infer_function`. |
| 616 | let param_values = infer_cx |
| 617 | .infer_var_values |
| 618 | .iter() |
| 619 | .map(|v| v.map_var(|InferVar(i)| Param(i))); |
| 620 | // Only allocate `param_values` if they constrain parameters. |
| 621 | let param_values = if param_values.clone().any(|v| v != Value::Unknown) { |
| 622 | Some(param_values.collect()) |
| 623 | } else { |
| 624 | None |
no test coverage detected