Skip to content

Commit e257df1

Browse files
Provide a method to attach a database even if it's different from the current attached one (#992)
* Provide a method to attach a database even if it's different from the current attached one rust-analyzer needs this. * Fix Clippy on beta * Update compile fail test outputs --------- Co-authored-by: Lukas Wirth <[email protected]>
1 parent 3713cd7 commit e257df1

File tree

4 files changed

+57
-5
lines changed

4 files changed

+57
-5
lines changed

src/attach.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,38 @@ impl Attached {
7979
op()
8080
}
8181

82+
#[inline]
83+
fn attach_allow_change<Db, R>(&self, db: &Db, op: impl FnOnce() -> R) -> R
84+
where
85+
Db: ?Sized + Database,
86+
{
87+
struct DbGuard<'s> {
88+
state: &'s Attached,
89+
prev: Option<NonNull<dyn Database>>,
90+
}
91+
92+
impl<'s> DbGuard<'s> {
93+
#[inline]
94+
fn new(attached: &'s Attached, db: &dyn Database) -> Self {
95+
let prev = attached.database.replace(Some(NonNull::from(db)));
96+
Self {
97+
state: attached,
98+
prev,
99+
}
100+
}
101+
}
102+
103+
impl Drop for DbGuard<'_> {
104+
#[inline]
105+
fn drop(&mut self) {
106+
self.state.database.set(self.prev);
107+
}
108+
}
109+
110+
let _guard = DbGuard::new(self, db.as_dyn_database());
111+
op()
112+
}
113+
82114
/// Access the "attached" database. Returns `None` if no database is attached.
83115
/// Databases are attached with `attach_database`.
84116
#[inline]
@@ -104,6 +136,23 @@ where
104136
)
105137
}
106138

139+
/// Attach the database to the current thread and execute `op`.
140+
/// Allows a different database than currently attached. The original database
141+
/// will be restored on return.
142+
///
143+
/// **Note:** Switching databases can cause bugs. If you do not intend to switch
144+
/// databases, prefer [`attach`] which will panic if you accidentally do.
145+
#[inline]
146+
pub fn attach_allow_change<R, Db>(db: &Db, op: impl FnOnce() -> R) -> R
147+
where
148+
Db: ?Sized + Database,
149+
{
150+
ATTACHED.with(
151+
#[inline]
152+
|a| a.attach_allow_change(db, op),
153+
)
154+
}
155+
107156
/// Access the "attached" database. Returns `None` if no database is attached.
108157
/// Databases are attached with `attach_database`.
109158
#[inline]

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub use self::runtime::Runtime;
6767
pub use self::storage::{Storage, StorageHandle};
6868
pub use self::update::Update;
6969
pub use self::zalsa::IngredientIndex;
70-
pub use crate::attach::{attach, with_attached_database};
70+
pub use crate::attach::{attach, attach_allow_change, with_attached_database};
7171

7272
pub mod prelude {
7373
#[cfg(feature = "accumulator")]

src/zalsa.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,9 @@ impl ErasedJar {
516516
pub const fn erase<I: HasJar>() -> Self {
517517
Self {
518518
kind: I::KIND,
519+
// This is a false positive of the lint on beta, fixed on nightly.
520+
// FIXME: Remove this when nightly stabilizes.
521+
#[allow(clippy::incompatible_msrv)]
519522
type_id: TypeId::of::<I::Jar>,
520523
type_name: std::any::type_name::<I::Jar>,
521524
create_ingredients: <I::Jar>::create_ingredients,

tests/compile-fail/incomplete_persistence.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: the trait bound `NotPersistable<'_>: Serialize` is not satisfied
1+
error[E0277]: the trait bound `NotPersistable<'_>: serde::Serialize` is not satisfied
22
--> tests/compile-fail/incomplete_persistence.rs:1:1
33
|
44
1 | #[salsa::tracked(persist)]
@@ -22,7 +22,7 @@ error[E0277]: the trait bound `NotPersistable<'_>: Serialize` is not satisfied
2222
= note: required for `(NotPersistable<'_>,)` to implement `Serialize`
2323
= note: this error originates in the macro `salsa::plumbing::setup_tracked_struct` which comes from the expansion of the attribute macro `salsa::tracked` (in Nightly builds, run with -Z macro-backtrace for more info)
2424

25-
error[E0277]: the trait bound `NotPersistable<'_>: Deserialize<'_>` is not satisfied
25+
error[E0277]: the trait bound `NotPersistable<'_>: serde::Deserialize<'de>` is not satisfied
2626
--> tests/compile-fail/incomplete_persistence.rs:1:1
2727
|
2828
1 | #[salsa::tracked(persist)]
@@ -43,7 +43,7 @@ error[E0277]: the trait bound `NotPersistable<'_>: Deserialize<'_>` is not satis
4343
= note: required for `(NotPersistable<'_>,)` to implement `Deserialize<'_>`
4444
= note: this error originates in the macro `salsa::plumbing::setup_tracked_struct` which comes from the expansion of the attribute macro `salsa::tracked` (in Nightly builds, run with -Z macro-backtrace for more info)
4545

46-
error[E0277]: the trait bound `NotPersistable<'db>: Serialize` is not satisfied
46+
error[E0277]: the trait bound `NotPersistable<'db>: serde::Serialize` is not satisfied
4747
--> tests/compile-fail/incomplete_persistence.rs:12:45
4848
|
4949
12 | fn query(_db: &dyn salsa::Database, _input: NotPersistable<'_>) {}
@@ -71,7 +71,7 @@ note: required by a bound in `query_input_is_persistable`
7171
| required by this bound in `query_input_is_persistable`
7272
= note: this error originates in the macro `salsa::plumbing::setup_tracked_fn` which comes from the expansion of the attribute macro `salsa::tracked` (in Nightly builds, run with -Z macro-backtrace for more info)
7373

74-
error[E0277]: the trait bound `for<'de> NotPersistable<'db>: Deserialize<'de>` is not satisfied
74+
error[E0277]: the trait bound `NotPersistable<'db>: serde::Deserialize<'de>` is not satisfied
7575
--> tests/compile-fail/incomplete_persistence.rs:12:45
7676
|
7777
12 | fn query(_db: &dyn salsa::Database, _input: NotPersistable<'_>) {}

0 commit comments

Comments
 (0)