Merge pull request #20669 from ChayimFriedman2/testing-guide
internal: Add a testing guide
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs
index f559230..82d670c 100644
--- a/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -129,6 +129,40 @@
}
#[test]
+fn regression_type_checker_does_not_eagerly_select_predicates_from_where_clauses() {
+ // This was a very long standing issue (#5514) with a lot of duplicates, that was
+ // fixed by the switch to the new trait solver, so it deserves a long name and a
+ // honorable mention.
+ check_infer(
+ r#"
+//- minicore: from
+
+struct Foo;
+impl Foo {
+ fn method(self) -> i32 { 0 }
+}
+
+fn f<T: Into<Foo>>(u: T) {
+ let x = u.into();
+ x.method();
+}
+ "#,
+ expect![[r#"
+ 38..42 'self': Foo
+ 51..56 '{ 0 }': i32
+ 53..54 '0': i32
+ 79..80 'u': T
+ 85..126 '{ ...d(); }': ()
+ 95..96 'x': Foo
+ 99..100 'u': T
+ 99..107 'u.into()': Foo
+ 113..114 'x': Foo
+ 113..123 'x.method()': i32
+ "#]],
+ );
+}
+
+#[test]
fn opaque_generics() {
check_infer(
r#"
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}`")),
+ }
+ }
+}