message: Improve error message for wrong target names
diff: //! repeats until the queue is empty.
  use std::collections::{BTreeSet, HashMap, HashSet};
  +use std::fmt::Write;
  use std::hash::{Hash, Hasher};
  use std::sync::Arc;
  @@ -1526,12 +1527,16 @@ fn find_named_targets<'a>(
  };
  if proposals.is_empty() {
  - let targets = packages.iter().flat_map(|pkg| {
  + let targets = packages
  + .iter()
  + .flat_map(|pkg| {
  pkg.targets()
  .iter()
  .filter(|target| is_expected_kind(target))
  - });
  - let suggestion = closest_msg(target_name, targets, |t| t.name());
  + })
  + .collect::<Vec<_>>();
  + let suggestion = closest_msg(target_name, targets.iter(), |t| t.name());
  + if !suggestion.is_empty() {
  anyhow::bail!(
  "no {} target {} `{}`{}",
  target_desc,
  @@ -1539,6 +1544,23 @@ fn find_named_targets<'a>(
  target_name,
  suggestion
  );
  + } else {
  + let mut msg = String::new();
  + writeln!(
  + msg,
  + "no {} target {} `{}`.",
  + target_desc,
  + if is_glob { "matches pattern" } else { "named" },
  + target_name,
  + )?;
  + if !targets.is_empty() {
  + writeln!(msg, "Available {} targets:", target_desc)?;
  + for target in targets {
  + writeln!(msg, " {}", target.name())?;
  + }
  + }
  + anyhow::bail!(msg);
  + }
  }
  Ok(proposals)
  }
  