Skip to content

Commit 185f9de

Browse files
authored
Merge pull request #19351 from davidbarsky/davidbarsky/fix-panic-in-diagnostics
internal: don't panic when the crate graph isn't ready
2 parents 3fc655b + 788232b commit 185f9de

File tree

14 files changed

+50
-30
lines changed

14 files changed

+50
-30
lines changed

crates/base-db/src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -212,22 +212,21 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database {
212212

213213
/// Returns the crates in topological order.
214214
///
215-
/// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications.
215+
/// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications.
216216
#[salsa::input]
217217
fn all_crates(&self) -> Arc<Box<[Crate]>>;
218218

219219
/// Returns an iterator over all transitive dependencies of the given crate,
220220
/// including the crate itself.
221221
///
222-
/// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications.
223-
///
222+
/// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications.
224223
#[salsa::transparent]
225224
fn transitive_deps(&self, crate_id: Crate) -> FxHashSet<Crate>;
226225

227226
/// Returns all transitive reverse dependencies of the given crate,
228227
/// including the crate itself.
229228
///
230-
/// **Warning**: Do not use this query in analysis! It kills incrementality across crate metadata modifications.
229+
/// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications.
231230
#[salsa::invoke(input::transitive_rev_deps)]
232231
#[salsa::transparent]
233232
fn transitive_rev_deps(&self, of: Crate) -> FxHashSet<Crate>;

crates/hir-def/src/nameres/tests/macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,7 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
10951095
}
10961096
"#,
10971097
);
1098-
let krate = *db.all_crates().last().unwrap();
1098+
let krate = *db.all_crates().last().expect("no crate graph present");
10991099
let def_map = db.crate_def_map(krate);
11001100

11011101
assert_eq!(def_map.data.exported_derives.len(), 1);
@@ -1445,7 +1445,7 @@ struct TokenStream;
14451445
fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
14461446
"#,
14471447
);
1448-
let krate = *db.all_crates().last().unwrap();
1448+
let krate = *db.all_crates().last().expect("no crate graph present");
14491449
let def_map = db.crate_def_map(krate);
14501450

14511451
let root_module = &def_map[DefMap::ROOT].scope;

crates/hir-ty/src/consteval/tests.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ fn check_answer(
101101
fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
102102
let mut err = String::new();
103103
let span_formatter = |file, range| format!("{file:?} {range:?}");
104-
let display_target = DisplayTarget::from_crate(&db, *db.all_crates().last().unwrap());
104+
let display_target =
105+
DisplayTarget::from_crate(&db, *db.all_crates().last().expect("no crate graph present"));
105106
match e {
106107
ConstEvalError::MirLowerError(e) => {
107108
e.pretty_print(&mut err, &db, span_formatter, display_target)

crates/hir/src/semantics.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,11 @@ impl<'db> SemanticsImpl<'db> {
314314
tree
315315
}
316316

317-
/// If not crate is found for the file, returns the last crate in topological order.
318-
pub fn first_crate_or_default(&self, file: FileId) -> Crate {
317+
/// If not crate is found for the file, try to return the last crate in topological order.
318+
pub fn first_crate(&self, file: FileId) -> Option<Crate> {
319319
match self.file_to_module_defs(file).next() {
320-
Some(module) => module.krate(),
321-
None => (*self.db.all_crates().last().unwrap()).into(),
320+
Some(module) => Some(module.krate()),
321+
None => self.db.all_crates().last().copied().map(Into::into),
322322
}
323323
}
324324

crates/hir/src/symbols.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ impl<'a> SymbolCollector<'a> {
7777
symbols: Default::default(),
7878
work: Default::default(),
7979
current_container_name: None,
80-
display_target: DisplayTarget::from_crate(db, *db.all_crates().last().unwrap()),
80+
display_target: DisplayTarget::from_crate(
81+
db,
82+
*db.all_crates().last().expect("no crate graph present"),
83+
),
8184
}
8285
}
8386

crates/ide-diagnostics/src/lib.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,17 @@ pub fn semantic_diagnostics(
389389
module.and_then(|m| db.toolchain_channel(m.krate().into())),
390390
Some(ReleaseChannel::Nightly) | None
391391
);
392-
let krate = module
393-
.map(|module| module.krate())
394-
.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into());
392+
393+
let krate = match module {
394+
Some(module) => module.krate(),
395+
None => {
396+
match db.all_crates().last() {
397+
Some(last) => (*last).into(),
398+
// short-circuit, return an empty vec of diagnostics
399+
None => return vec![],
400+
}
401+
}
402+
};
395403
let display_target = krate.to_display_target(db);
396404
let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target };
397405

crates/ide-ssr/src/matching.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -626,11 +626,9 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
626626
match_error!("Failed to get receiver type for `{}`", expr.syntax().text())
627627
})?
628628
.original;
629-
let krate = self
630-
.sema
631-
.scope(expr.syntax())
632-
.map(|it| it.krate())
633-
.unwrap_or_else(|| hir::Crate::from(*self.sema.db.all_crates().last().unwrap()));
629+
let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| {
630+
hir::Crate::from(*self.sema.db.all_crates().last().expect("no crate graph present"))
631+
});
634632
let res = code_type
635633
.autoderef(self.sema.db)
636634
.enumerate()

crates/ide/src/hover.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ pub(crate) fn hover(
130130
let file = sema.parse_guess_edition(file_id).syntax().clone();
131131
let edition =
132132
sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
133-
let display_target = sema.first_crate_or_default(file_id).to_display_target(db);
133+
let display_target = sema.first_crate(file_id)?.to_display_target(db);
134134
let mut res = if range.is_empty() {
135135
hover_offset(
136136
sema,

crates/ide/src/inlay_hints.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,10 @@ fn hints(
211211
file_id: EditionedFileId,
212212
node: SyntaxNode,
213213
) {
214-
let display_target = sema.first_crate_or_default(file_id.file_id()).to_display_target(sema.db);
214+
let Some(krate) = sema.first_crate(file_id.file_id()) else {
215+
return;
216+
};
217+
let display_target = krate.to_display_target(sema.db);
215218
closing_brace::hints(hints, sema, config, file_id, display_target, node.clone());
216219
if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
217220
generic_param::hints(hints, famous_defs, config, any_has_generic_args);

crates/ide/src/runnables.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,9 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
498498
};
499499
let krate = def.krate(db);
500500
let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
501-
let display_target =
502-
krate.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()).to_display_target(db);
501+
let display_target = krate
502+
.unwrap_or_else(|| (*db.all_crates().last().expect("no crate graph present")).into())
503+
.to_display_target(db);
503504
if !has_runnable_doc_test(&attrs) {
504505
return None;
505506
}

crates/ide/src/signature_help.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub(crate) fn signature_help(
8484
let token = sema.descend_into_macros_single_exact(token);
8585
let edition =
8686
sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
87-
let display_target = sema.first_crate_or_default(file_id).to_display_target(db);
87+
let display_target = sema.first_crate(file_id)?.to_display_target(db);
8888

8989
for node in token.parent_ancestors() {
9090
match_ast! {

crates/ide/src/static_index.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ fn documentation_for_definition(
119119
sema.db,
120120
famous_defs.as_ref(),
121121
def.krate(sema.db)
122-
.unwrap_or_else(|| (*sema.db.all_crates().last().unwrap()).into())
122+
.unwrap_or_else(|| {
123+
(*sema.db.all_crates().last().expect("no crate graph present")).into()
124+
})
123125
.to_display_target(sema.db),
124126
)
125127
}
@@ -175,7 +177,10 @@ impl StaticIndex<'_> {
175177
let root = sema.parse_guess_edition(file_id).syntax().clone();
176178
let edition =
177179
sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
178-
let display_target = sema.first_crate_or_default(file_id).to_display_target(self.db);
180+
let display_target = match sema.first_crate(file_id) {
181+
Some(krate) => krate.to_display_target(sema.db),
182+
None => return,
183+
};
179184
let tokens = root.descendants_with_tokens().filter_map(|it| match it {
180185
syntax::NodeOrToken::Node(_) => None,
181186
syntax::NodeOrToken::Token(it) => Some(it),

crates/ide/src/view_memory_layout.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub(crate) fn view_memory_layout(
8383
) -> Option<RecursiveMemoryLayout> {
8484
let sema = Semantics::new(db);
8585
let file = sema.parse_guess_edition(position.file_id);
86-
let display_target = sema.first_crate_or_default(position.file_id).to_display_target(db);
86+
let display_target = sema.first_crate(position.file_id)?.to_display_target(db);
8787
let token =
8888
pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
8989
SyntaxKind::IDENT => 3,

crates/rust-analyzer/src/cli/analysis_stats.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,10 @@ impl flags::AnalysisStats {
384384

385385
for &file_id in &file_ids {
386386
let sema = hir::Semantics::new(db);
387-
let display_target =
388-
sema.first_crate_or_default(file_id.file_id()).to_display_target(db);
387+
let display_target = match sema.first_crate(file_id.file_id()) {
388+
Some(krate) => krate.to_display_target(sema.db),
389+
None => continue,
390+
};
389391

390392
let parse = sema.parse_guess_edition(file_id.into());
391393
let file_txt = db.file_text(file_id.into());

0 commit comments

Comments
 (0)