# cached 1.0 → 1.1 Migration (Agent Instructions)

Versions: `cached 1.0` → `cached 1.1` / `cached_proc_macro 1.0` → `cached_proc_macro 1.1`

## Breaking changes

None. This release is purely additive.

## Required Cargo.toml change

```toml
# Before
cached = "1.0"

# After
cached = "1.1"
```

If pinning the proc-macro crate directly:
```toml
cached_proc_macro = "1.1"
```

`cached_proc_macro_types` did not change; leave it at `"1.0"` if pinned.

## New APIs (additive — no action required unless adopting)

### `ExpiringCache<K, V>` store

New unbounded store where each value determines its own expiration via the
`Expires` trait. `ExpiringLruCache<K, V>` (the LRU-bounded sibling) already
existed; `ExpiringCache` adds the unbounded variant.

```rust
use cached::{ExpiringCache, Expires};

struct Session { expires_at: Instant }
impl Expires for Session {
    fn is_expired(&self) -> bool { Instant::now() >= self.expires_at }
}

let cache: ExpiringCache<u64, Session> = ExpiringCache::new();
```

### `expires = true` on `#[cached]` and `#[once]`

New attribute selects the matching expiring store automatically:
- `#[cached(expires = true)]` — selects `ExpiringCache` (unbounded) or
  `ExpiringLruCache` (when `size` is also set).
- `#[once(expires = true)]` — the single cached value controls its own TTL.

Mutually exclusive with `ttl`, `ty`, `create`, `with_cached_flag`, `unsync_reads`,
`refresh`, and `unbound` on `#[cached]`.

```rust
use cached::macros::cached;

#[cached(expires = true)]
fn get_session(id: u64) -> Session { /* ... */ }

#[cached(expires = true, size = 1000)]
fn get_bounded(id: u64) -> Session { /* ... */ }
```

### `TtlSortedCache` and `ExpiringCache` gained `Debug` and `Clone`

If code previously special-cased the absence of these derives on those two
types, that guard can be removed.

## VERIFY

`cargo build` — no new compile errors expected from the version bump alone.
