11//! base_db defines basic database traits. The concrete DB is defined by ide.
2+
3+ pub use salsa;
4+ pub use salsa_macros;
5+
26// FIXME: Rename this crate, base db is non descriptive
37mod change;
48mod input;
59
6- use std:: hash:: BuildHasherDefault ;
10+ use std:: { cell :: RefCell , hash:: BuildHasherDefault , panic , sync :: Once } ;
711
812pub use crate :: {
913 change:: FileChange ,
@@ -17,7 +21,6 @@ pub use crate::{
1721use dashmap:: { DashMap , mapref:: entry:: Entry } ;
1822pub use query_group:: { self } ;
1923use rustc_hash:: { FxHashSet , FxHasher } ;
20- pub use salsa:: { self } ;
2124use salsa:: { Durability , Setter } ;
2225pub use semver:: { BuildMetadata , Prerelease , Version , VersionReq } ;
2326use span:: Edition ;
@@ -28,7 +31,7 @@ pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}
2831#[ macro_export]
2932macro_rules! impl_intern_key {
3033 ( $id: ident, $loc: ident) => {
31- #[ salsa :: interned( no_lifetime) ]
34+ #[ salsa_macros :: interned( no_lifetime) ]
3235 pub struct $id {
3336 pub loc: $loc,
3437 }
@@ -57,7 +60,12 @@ pub struct Files {
5760
5861impl Files {
5962 pub fn file_text ( & self , file_id : vfs:: FileId ) -> FileText {
60- * self . files . get ( & file_id) . expect ( "Unable to fetch file; this is a bug" )
63+ match self . files . get ( & file_id) {
64+ Some ( text) => * text,
65+ None => {
66+ panic ! ( "Unable to fetch file text for `vfs::FileId`: {file_id:?}; this is a bug" )
67+ }
68+ }
6169 }
6270
6371 pub fn set_file_text ( & self , db : & mut dyn SourceDatabase , file_id : vfs:: FileId , text : & str ) {
@@ -93,10 +101,12 @@ impl Files {
93101
94102 /// Source root of the file.
95103 pub fn source_root ( & self , source_root_id : SourceRootId ) -> SourceRootInput {
96- let source_root = self
97- . source_roots
98- . get ( & source_root_id)
99- . expect ( "Unable to fetch source root id; this is a bug" ) ;
104+ let source_root = match self . source_roots . get ( & source_root_id) {
105+ Some ( source_root) => source_root,
106+ None => panic ! (
107+ "Unable to fetch `SourceRootInput` with `SourceRootId` ({source_root_id:?}); this is a bug"
108+ ) ,
109+ } ;
100110
101111 * source_root
102112 }
@@ -121,10 +131,12 @@ impl Files {
121131 }
122132
123133 pub fn file_source_root ( & self , id : vfs:: FileId ) -> FileSourceRootInput {
124- let file_source_root = self
125- . file_source_roots
126- . get ( & id)
127- . expect ( "Unable to fetch FileSourceRootInput; this is a bug" ) ;
134+ let file_source_root = match self . file_source_roots . get ( & id) {
135+ Some ( file_source_root) => file_source_root,
136+ None => panic ! (
137+ "Unable to get `FileSourceRootInput` with `vfs::FileId` ({id:?}); this is a bug" ,
138+ ) ,
139+ } ;
128140 * file_source_root
129141 }
130142
@@ -152,7 +164,7 @@ impl Files {
152164 }
153165}
154166
155- #[ salsa :: interned( no_lifetime, debug, constructor=from_span) ]
167+ #[ salsa_macros :: interned( no_lifetime, debug, constructor=from_span) ]
156168pub struct EditionedFileId {
157169 pub editioned_file_id : span:: EditionedFileId ,
158170}
@@ -187,18 +199,18 @@ impl EditionedFileId {
187199 }
188200}
189201
190- #[ salsa :: input( debug) ]
202+ #[ salsa_macros :: input( debug) ]
191203pub struct FileText {
192204 pub text : Arc < str > ,
193205 pub file_id : vfs:: FileId ,
194206}
195207
196- #[ salsa :: input( debug) ]
208+ #[ salsa_macros :: input( debug) ]
197209pub struct FileSourceRootInput {
198210 pub source_root_id : SourceRootId ,
199211}
200212
201- #[ salsa :: input( debug) ]
213+ #[ salsa_macros :: input( debug) ]
202214pub struct SourceRootInput {
203215 pub source_root : Arc < SourceRoot > ,
204216}
@@ -265,7 +277,7 @@ pub fn transitive_deps(db: &dyn SourceDatabase, crate_id: Crate) -> FxHashSet<Cr
265277 deps
266278}
267279
268- #[ salsa :: db]
280+ #[ salsa_macros :: db]
269281pub trait SourceDatabase : salsa:: Database {
270282 /// Text of the file.
271283 fn file_text ( & self , file_id : vfs:: FileId ) -> FileText ;
@@ -344,7 +356,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFil
344356}
345357
346358fn parse_errors ( db : & dyn RootQueryDb , file_id : EditionedFileId ) -> Option < & [ SyntaxError ] > {
347- #[ salsa :: tracked( return_ref) ]
359+ #[ salsa_macros :: tracked( return_ref) ]
348360 fn parse_errors ( db : & dyn RootQueryDb , file_id : EditionedFileId ) -> Option < Box < [ SyntaxError ] > > {
349361 let errors = db. parse ( file_id) . errors ( ) ;
350362 match & * errors {
@@ -373,3 +385,49 @@ fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> {
373385 let source_root = db. file_source_root ( file_id) ;
374386 db. source_root_crates ( source_root. source_root_id ( db) )
375387}
388+
389+ #[ must_use]
390+ #[ non_exhaustive]
391+ pub struct DbPanicContext ;
392+
393+ impl Drop for DbPanicContext {
394+ fn drop ( & mut self ) {
395+ Self :: with_ctx ( |ctx| assert ! ( ctx. pop( ) . is_some( ) ) ) ;
396+ }
397+ }
398+
399+ impl DbPanicContext {
400+ pub fn enter ( frame : String ) -> DbPanicContext {
401+ #[ expect( clippy:: print_stderr, reason = "already panicking anyway" ) ]
402+ fn set_hook ( ) {
403+ let default_hook = panic:: take_hook ( ) ;
404+ panic:: set_hook ( Box :: new ( move |panic_info| {
405+ default_hook ( panic_info) ;
406+ if let Some ( backtrace) = salsa:: Backtrace :: capture ( ) {
407+ eprintln ! ( "{backtrace:#}" ) ;
408+ }
409+ DbPanicContext :: with_ctx ( |ctx| {
410+ if !ctx. is_empty ( ) {
411+ eprintln ! ( "additional context:" ) ;
412+ for ( idx, frame) in ctx. iter ( ) . enumerate ( ) {
413+ eprintln ! ( "{idx:>4}: {frame}\n " ) ;
414+ }
415+ }
416+ } ) ;
417+ } ) ) ;
418+ }
419+
420+ static SET_HOOK : Once = Once :: new ( ) ;
421+ SET_HOOK . call_once ( set_hook) ;
422+
423+ Self :: with_ctx ( |ctx| ctx. push ( frame) ) ;
424+ DbPanicContext
425+ }
426+
427+ fn with_ctx ( f : impl FnOnce ( & mut Vec < String > ) ) {
428+ thread_local ! {
429+ static CTX : RefCell <Vec <String >> = const { RefCell :: new( Vec :: new( ) ) } ;
430+ }
431+ CTX . with ( |ctx| f ( & mut ctx. borrow_mut ( ) ) ) ;
432+ }
433+ }
0 commit comments