message: Fix signature printing
  Summary: There was a bug in previous implementation: `SymbolMap` iteration is not ordered.
diff: @@ -253,28 +253,40 @@ impl<V> ParametersSpec<V> {
  // in some contexts, so don't delete it.
  }
  - /// Function parameter as they would appear in `def`
  - /// (excluding types, default values and formatting).
  - pub fn parameters_str(&self) -> String {
  - let mut collector = String::new();
  - let mut names = self.names.keys();
  - let mut next_name = || {
  + // Note, this is linear, making `parameters_str` quadratic.
  + fn name_by_index(&self, index: usize) -> &str {
  + self.names
  + .iter()
  + .find_map(|x| {
  + if x.1 == index {
  // We prepend '$' on the front of variable names that are positional-only
  // arguments to the native functions. We rip those off when
  // displaying the signature.
  // The `unwrap` is safe because we must have a names entry for each
  // non-Args/KWargs kind.
  - names.next().unwrap().as_str().trim_start_match('$')
  - };
  + Some(x.0.as_str().trim_start_match("$"))
  + } else {
  + None
  + }
  + })
  + .unwrap_or(
  + // Should not happen, but better than panic.
  + "?",
  + )
  + }
  + /// Function parameter as they would appear in `def`
  + /// (excluding types, default values and formatting).
  + pub fn parameters_str(&self) -> String {
  + let mut collector = String::new();
  for (i, typ) in self.kinds.iter().enumerate() {
  if i != 0 {
  collector.push_str(", ");
  }
  match typ {
  - ParameterKind::Required => collector.push_str(next_name()),
  + ParameterKind::Required => collector.push_str(self.name_by_index(i)),
  ParameterKind::Optional | ParameterKind::Defaulted(_) => {
  - collector.push_str(next_name());
  + collector.push_str(self.name_by_index(i));
  collector.push_str(" = ...");
  }
  ParameterKind::Args => collector.push_str("*args"),
  @@ -1258,11 +1270,11 @@ mod tests {
  fn test_parameters_str() {
  let a = Assert::new();
  let f = a
  - .pass_module("def f(a, b, *args, **kwargs): pass")
  + .pass_module("def f(a, b, c, d, e, f, g, h, *args, **kwargs): pass")
  .get("f")
  .unwrap();
  assert_eq!(
  - "a, b, *args, **kwargs",
  + "a, b, c, d, e, f, g, h, *args, **kwargs",
  &f.value().parameters_spec().unwrap().parameters_str()
  );
  }
  