Merge pull request #20667 from ChayimFriedman2/ns-cleanup2

internal: Add Regression Test For The One And The Only Issue #5514
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 3f52303..03b9b36 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -483,6 +483,12 @@
     db: &'db RootDatabase,
     ty: &hir::Type<'db>,
 ) -> Vec<(hir::Trait, Vec<(Option<hir::Type<'db>>, hir::Name)>)> {
+    if ty.is_unknown() {
+        // The trait solver returns "yes" to the question whether the error type
+        // impls any trait, and we don't want to show it as having any notable trait.
+        return Vec::new();
+    }
+
     db.notable_traits_in_deps(ty.krate(db).into())
         .iter()
         .flat_map(|it| &**it)
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 58d8a7e..a88c0c9 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -11097,3 +11097,26 @@
         "#]],
     );
 }
+
+#[test]
+fn unknown_should_not_implement_notable_traits() {
+    check(
+        r#"
+//- minicore: future, iterator
+fn foo() {
+    let x$0;
+}
+    "#,
+        expect![[r#"
+            *x*
+
+            ```rust
+            let x: {unknown}
+            ```
+
+            ---
+
+            no Drop
+        "#]],
+    );
+}
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 7b12cb1..82590c8 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -9,7 +9,7 @@
 use ide_db::{LineIndexDatabase, base_db::SourceDatabase};
 use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace_at};
 
-use crate::cli::flags;
+use crate::cli::{flags, progress_report::ProgressReport};
 
 impl flags::Diagnostics {
     pub fn run(self) -> anyhow::Result<()> {
@@ -50,23 +50,26 @@
 
         let mut found_error = false;
         let mut visited_files = FxHashSet::default();
+        let min_severity = self.severity.unwrap_or(flags::Severity::Weak);
 
-        let work = all_modules(db).into_iter().filter(|module| {
-            let file_id = module.definition_source_file_id(db).original_file(db);
-            let source_root = db.file_source_root(file_id.file_id(db)).source_root_id(db);
-            let source_root = db.source_root(source_root).source_root(db);
-            !source_root.is_library
-        });
+        let work = all_modules(db)
+            .into_iter()
+            .filter(|module| {
+                let file_id = module.definition_source_file_id(db).original_file(db);
+                let source_root = db.file_source_root(file_id.file_id(db)).source_root_id(db);
+                let source_root = db.source_root(source_root).source_root(db);
+                !source_root.is_library
+            })
+            .collect::<Vec<_>>();
 
+        let mut bar = ProgressReport::new(work.len());
         for module in work {
             let file_id = module.definition_source_file_id(db).original_file(db);
             if !visited_files.contains(&file_id) {
+                let message = format!("processing {}", _vfs.file_path(file_id.file_id(db)));
+                bar.set_message(move || message.clone());
                 let crate_name =
                     module.krate().display_name(db).as_deref().unwrap_or(&sym::unknown).to_owned();
-                println!(
-                    "processing crate: {crate_name}, module: {}",
-                    _vfs.file_path(file_id.file_id(db))
-                );
                 for diagnostic in analysis
                     .full_diagnostics(
                         &DiagnosticsConfig::test_sample(),
@@ -75,6 +78,16 @@
                     )
                     .unwrap()
                 {
+                    let severity = match diagnostic.severity {
+                        Severity::Error => flags::Severity::Error,
+                        Severity::Warning => flags::Severity::Warning,
+                        Severity::WeakWarning => flags::Severity::Weak,
+                        Severity::Allow => continue,
+                    };
+                    if severity < min_severity {
+                        continue;
+                    }
+
                     if matches!(diagnostic.severity, Severity::Error) {
                         found_error = true;
                     }
@@ -83,12 +96,17 @@
                     let line_index = db.line_index(range.file_id);
                     let start = line_index.line_col(range.range.start());
                     let end = line_index.line_col(range.range.end());
-                    println!("{severity:?} {code:?} from {start:?} to {end:?}: {message}");
+                    bar.println(format!(
+                        "at crate {crate_name}, file {}: {severity:?} {code:?} from {start:?} to {end:?}: {message}",
+                        _vfs.file_path(file_id.file_id(db))
+                    ));
                 }
 
                 visited_files.insert(file_id);
             }
+            bar.inc(1);
         }
+        bar.finish_and_clear();
 
         println!();
         println!("diagnostic scan complete");
diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs
index 16f3512..75030be 100644
--- a/crates/rust-analyzer/src/cli/flags.rs
+++ b/crates/rust-analyzer/src/cli/flags.rs
@@ -124,6 +124,9 @@
             optional --disable-proc-macros
             /// Run the proc-macro-srv binary at the specified path.
             optional --proc-macro-srv path: PathBuf
+
+            /// The minimum severity.
+            optional --severity severity: Severity
         }
 
         /// Report unresolved references
@@ -281,6 +284,7 @@
     pub disable_build_scripts: bool,
     pub disable_proc_macros: bool,
     pub proc_macro_srv: Option<PathBuf>,
+    pub severity: Option<Severity>,
 }
 
 #[derive(Debug)]
@@ -376,3 +380,23 @@
         }
     }
 }
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum Severity {
+    Weak,
+    Warning,
+    Error,
+}
+
+impl FromStr for Severity {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match &*s.to_ascii_lowercase() {
+            "weak" => Ok(Self::Weak),
+            "warning" => Ok(Self::Warning),
+            "error" => Ok(Self::Error),
+            _ => Err(format!("unknown severity `{s}`")),
+        }
+    }
+}