about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Barsky <me@davidbarsky.com>2025-03-13 19:46:01 +0000
committerGitHub <noreply@github.com>2025-03-13 19:46:01 +0000
commit35209f462bbb1506d03ae8b232c2d9f2b865f890 (patch)
tree0e5cda3ff6a25247c21d08a66fd31595c14bd61a
parent8148fa9324c274ae4be0e8f62a2d42adb8a371ff (diff)
parenta508206f4e39e28274f77e6f1eb6eac1bbb27191 (diff)
downloadrust-35209f462bbb1506d03ae8b232c2d9f2b865f890.tar.gz
rust-35209f462bbb1506d03ae8b232c2d9f2b865f890.zip
Merge pull request #19351 from davidbarsky/davidbarsky/fix-panic-in-diagnostics
internal: don't panic when the crate graph isn't ready
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/symbols.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs6
14 files changed, 50 insertions, 30 deletions
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index 324979b2e46..0f29abbb54f 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -212,22 +212,21 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database {
 
     /// Returns the crates in topological order.
     ///
-    /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications.
+    /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications.
     #[salsa::input]
     fn all_crates(&self) -> Arc<Box<[Crate]>>;
 
     /// Returns an iterator over all transitive dependencies of the given crate,
     /// including the crate itself.
     ///
-    /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications.
-    ///
+    /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications.
     #[salsa::transparent]
     fn transitive_deps(&self, crate_id: Crate) -> FxHashSet<Crate>;
 
     /// Returns all transitive reverse dependencies of the given crate,
     /// including the crate itself.
     ///
-    /// **Warning**: Do not use this query in analysis! It kills incrementality across crate metadata modifications.
+    /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications.
     #[salsa::invoke(input::transitive_rev_deps)]
     #[salsa::transparent]
     fn transitive_rev_deps(&self, of: Crate) -> FxHashSet<Crate>;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
index 0348a7076a8..5f8a01523d8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
@@ -1095,7 +1095,7 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
 }
 "#,
     );
-    let krate = *db.all_crates().last().unwrap();
+    let krate = *db.all_crates().last().expect("no crate graph present");
     let def_map = db.crate_def_map(krate);
 
     assert_eq!(def_map.data.exported_derives.len(), 1);
@@ -1445,7 +1445,7 @@ struct TokenStream;
 fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
     "#,
     );
-    let krate = *db.all_crates().last().unwrap();
+    let krate = *db.all_crates().last().expect("no crate graph present");
     let def_map = db.crate_def_map(krate);
 
     let root_module = &def_map[DefMap::ROOT].scope;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 37e7df6f4b4..d679f9dd7ca 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -101,7 +101,8 @@ fn check_answer(
 fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
     let mut err = String::new();
     let span_formatter = |file, range| format!("{file:?} {range:?}");
-    let display_target = DisplayTarget::from_crate(&db, *db.all_crates().last().unwrap());
+    let display_target =
+        DisplayTarget::from_crate(&db, *db.all_crates().last().expect("no crate graph present"));
     match e {
         ConstEvalError::MirLowerError(e) => {
             e.pretty_print(&mut err, &db, span_formatter, display_target)
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 6378eebd24f..15cd69f320d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -314,11 +314,11 @@ impl<'db> SemanticsImpl<'db> {
         tree
     }
 
-    /// If not crate is found for the file, returns the last crate in topological order.
-    pub fn first_crate_or_default(&self, file: FileId) -> Crate {
+    /// If not crate is found for the file, try to return the last crate in topological order.
+    pub fn first_crate(&self, file: FileId) -> Option<Crate> {
         match self.file_to_module_defs(file).next() {
-            Some(module) => module.krate(),
-            None => (*self.db.all_crates().last().unwrap()).into(),
+            Some(module) => Some(module.krate()),
+            None => self.db.all_crates().last().copied().map(Into::into),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index cc8aa1f1a18..2a6c15207a3 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -77,7 +77,10 @@ impl<'a> SymbolCollector<'a> {
             symbols: Default::default(),
             work: Default::default(),
             current_container_name: None,
-            display_target: DisplayTarget::from_crate(db, *db.all_crates().last().unwrap()),
+            display_target: DisplayTarget::from_crate(
+                db,
+                *db.all_crates().last().expect("no crate graph present"),
+            ),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index f4ced736b3d..dc6fd1f5eae 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -389,9 +389,17 @@ pub fn semantic_diagnostics(
         module.and_then(|m| db.toolchain_channel(m.krate().into())),
         Some(ReleaseChannel::Nightly) | None
     );
-    let krate = module
-        .map(|module| module.krate())
-        .unwrap_or_else(|| (*db.all_crates().last().unwrap()).into());
+
+    let krate = match module {
+        Some(module) => module.krate(),
+        None => {
+            match db.all_crates().last() {
+                Some(last) => (*last).into(),
+                // short-circuit, return an empty vec of diagnostics
+                None => return vec![],
+            }
+        }
+    };
     let display_target = krate.to_display_target(db);
     let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target };
 
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
index 48d2431a11f..a76516f44f0 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -626,11 +626,9 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
                 match_error!("Failed to get receiver type for `{}`", expr.syntax().text())
             })?
             .original;
-        let krate = self
-            .sema
-            .scope(expr.syntax())
-            .map(|it| it.krate())
-            .unwrap_or_else(|| hir::Crate::from(*self.sema.db.all_crates().last().unwrap()));
+        let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| {
+            hir::Crate::from(*self.sema.db.all_crates().last().expect("no crate graph present"))
+        });
         let res = code_type
             .autoderef(self.sema.db)
             .enumerate()
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index b00de6ba408..04189ed52aa 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -130,7 +130,7 @@ pub(crate) fn hover(
     let file = sema.parse_guess_edition(file_id).syntax().clone();
     let edition =
         sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
-    let display_target = sema.first_crate_or_default(file_id).to_display_target(db);
+    let display_target = sema.first_crate(file_id)?.to_display_target(db);
     let mut res = if range.is_empty() {
         hover_offset(
             sema,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 3a709e71fbe..57adf3e2a47 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -211,7 +211,10 @@ fn hints(
     file_id: EditionedFileId,
     node: SyntaxNode,
 ) {
-    let display_target = sema.first_crate_or_default(file_id.file_id()).to_display_target(sema.db);
+    let Some(krate) = sema.first_crate(file_id.file_id()) else {
+        return;
+    };
+    let display_target = krate.to_display_target(sema.db);
     closing_brace::hints(hints, sema, config, file_id, display_target, node.clone());
     if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
         generic_param::hints(hints, famous_defs, config, any_has_generic_args);
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index baa7ee68973..f2cb3c1f991 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -498,8 +498,9 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
     };
     let krate = def.krate(db);
     let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
-    let display_target =
-        krate.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()).to_display_target(db);
+    let display_target = krate
+        .unwrap_or_else(|| (*db.all_crates().last().expect("no crate graph present")).into())
+        .to_display_target(db);
     if !has_runnable_doc_test(&attrs) {
         return None;
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index b5468a5aee9..84912f6be65 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -84,7 +84,7 @@ pub(crate) fn signature_help(
     let token = sema.descend_into_macros_single_exact(token);
     let edition =
         sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
-    let display_target = sema.first_crate_or_default(file_id).to_display_target(db);
+    let display_target = sema.first_crate(file_id)?.to_display_target(db);
 
     for node in token.parent_ancestors() {
         match_ast! {
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index 5a2b09b5137..c1562769309 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -119,7 +119,9 @@ fn documentation_for_definition(
         sema.db,
         famous_defs.as_ref(),
         def.krate(sema.db)
-            .unwrap_or_else(|| (*sema.db.all_crates().last().unwrap()).into())
+            .unwrap_or_else(|| {
+                (*sema.db.all_crates().last().expect("no crate graph present")).into()
+            })
             .to_display_target(sema.db),
     )
 }
@@ -175,7 +177,10 @@ impl StaticIndex<'_> {
         let root = sema.parse_guess_edition(file_id).syntax().clone();
         let edition =
             sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
-        let display_target = sema.first_crate_or_default(file_id).to_display_target(self.db);
+        let display_target = match sema.first_crate(file_id) {
+            Some(krate) => krate.to_display_target(sema.db),
+            None => return,
+        };
         let tokens = root.descendants_with_tokens().filter_map(|it| match it {
             syntax::NodeOrToken::Node(_) => None,
             syntax::NodeOrToken::Token(it) => Some(it),
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
index 34bca7bce12..02e3b1d500f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
@@ -83,7 +83,7 @@ pub(crate) fn view_memory_layout(
 ) -> Option<RecursiveMemoryLayout> {
     let sema = Semantics::new(db);
     let file = sema.parse_guess_edition(position.file_id);
-    let display_target = sema.first_crate_or_default(position.file_id).to_display_target(db);
+    let display_target = sema.first_crate(position.file_id)?.to_display_target(db);
     let token =
         pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
             SyntaxKind::IDENT => 3,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index a391a01fae7..1efc242bfb6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -384,8 +384,10 @@ impl flags::AnalysisStats {
 
         for &file_id in &file_ids {
             let sema = hir::Semantics::new(db);
-            let display_target =
-                sema.first_crate_or_default(file_id.file_id()).to_display_target(db);
+            let display_target = match sema.first_crate(file_id.file_id()) {
+                Some(krate) => krate.to_display_target(sema.db),
+                None => continue,
+            };
 
             let parse = sema.parse_guess_edition(file_id.into());
             let file_txt = db.file_text(file_id.into());