@@ -13,10 +13,17 @@ struct Input {
13
13
}
14
14
15
15
#[ salsa:: interned]
16
+ #[ derive( Debug ) ]
16
17
struct Interned < ' db > {
17
18
field1 : usize ,
18
19
}
19
20
21
+ #[ salsa:: interned]
22
+ #[ derive( Debug ) ]
23
+ struct NestedInterned < ' db > {
24
+ interned : Interned < ' db > ,
25
+ }
26
+
20
27
#[ test]
21
28
fn test_intern_new ( ) {
22
29
#[ salsa:: tracked]
@@ -257,3 +264,72 @@ fn test_reuse_interned_input() {
257
264
let result = use_interned ( & db, interned) ;
258
265
assert_eq ! ( result, 2 ) ;
259
266
}
267
+
268
+ #[ test]
269
+ fn test_reuse_multiple_interned_input ( ) {
270
+ // A query that creates an interned value.
271
+ #[ salsa:: tracked]
272
+ fn create_interned < ' db > ( db : & ' db dyn Database , input : Input ) -> Interned < ' db > {
273
+ Interned :: new ( db, input. field1 ( db) )
274
+ }
275
+
276
+ // A query that creates an interned value.
277
+ #[ salsa:: tracked]
278
+ fn create_nested_interned < ' db > (
279
+ db : & ' db dyn Database ,
280
+ interned : Interned < ' db > ,
281
+ ) -> NestedInterned < ' db > {
282
+ NestedInterned :: new ( db, interned)
283
+ }
284
+
285
+ #[ salsa:: tracked]
286
+ fn use_interned < ' db > ( db : & ' db dyn Database , interned : Interned < ' db > ) -> usize {
287
+ let field = interned. field1 ( db) ;
288
+ field
289
+ }
290
+
291
+ // A query that reads an interned value.
292
+ #[ salsa:: tracked]
293
+ fn use_nested_interned < ' db > (
294
+ db : & ' db dyn Database ,
295
+ nested_interned : NestedInterned < ' db > ,
296
+ ) -> usize {
297
+ nested_interned. interned ( db) . field1 ( db)
298
+ }
299
+
300
+ let mut db = common:: EventLoggerDatabase :: default ( ) ;
301
+ let input = Input :: new ( & db, 0 ) ;
302
+
303
+ // Create and use NI0, which wraps I0, in R0.
304
+ let interned = create_interned ( & db, input) ;
305
+ let i0_id = salsa:: plumbing:: AsId :: as_id ( & interned) ;
306
+ let nested_interned = create_nested_interned ( & db, interned) ;
307
+ let result = use_nested_interned ( & db, nested_interned) ;
308
+ assert_eq ! ( result, 0 ) ;
309
+
310
+ // Create and use I1 in a number of revisions, marking I0 as stale.
311
+ input. set_field1 ( & mut db) . to ( 1 ) ;
312
+ for _ in 0 ..10 {
313
+ let interned = create_interned ( & db, input) ;
314
+ let result = use_interned ( & db, interned) ;
315
+ assert_eq ! ( result, 1 ) ;
316
+
317
+ // Trigger a new revision.
318
+ input. set_field1 ( & mut db) . to ( 1 ) ;
319
+ }
320
+
321
+ // Create I2, reusing the stale slot of I0.
322
+ input. set_field1 ( & mut db) . to ( 2 ) ;
323
+ let interned = create_interned ( & db, input) ;
324
+
325
+ let i2_id = salsa:: plumbing:: AsId :: as_id ( & interned) ;
326
+ assert_eq ! ( i0_id, i2_id) ;
327
+
328
+ // Create NI1 wrapping I2 instead of I0.
329
+ let nested_interned = create_nested_interned ( & db, interned) ;
330
+
331
+ // Use NI1. The function should not be memoized with the value of NI0,
332
+ // despite I2 and I0 sharing the same ID.
333
+ let result = use_nested_interned ( & db, nested_interned) ;
334
+ assert_eq ! ( result, 2 ) ;
335
+ }
0 commit comments