| name | rust-lifetime-complex |
| description | Advanced lifetime expert covering HRTB, GAT, 'static bounds, trait object constraints, type system conflicts, and lifetime elision edge cases.triggers: - lifetime - HRTB - GAT - higher-ranked - 'static - trait object - one type is more general - lifetime conflict--- # Advanced Lifetime and Type System Expert ## Core Question **Why won't this type conversion compile?** The type system's boundaries are often surprising. |
Solution Patterns
Pattern 1: HRTB (Higher-Ranked Trait Bounds)
type ClosureFn<T> = dyn for<'a> FnOnce(&'a mut Connection) -> BoxFuture<'a, T>;
async fn with_connection<F, T, Fut>(f: F) -> Result<T, Error>
where
F: for<'c> FnOnce(&'c mut Connection) -> Fut,
Fut: Future<Output = Result<T, Error>>,
{
let mut conn = get_connection().await?;
f(&mut conn).await
}
with_connection(|conn| async move {
query("SELECT * FROM users").fetch_all(conn).await
}).await?;
Pattern 2: GAT + Object Safety
trait Repository {
type Row<'a>: RowView<'a>;
fn query<'a>(&'a self) -> Vec<Self::Row<'a>>;
}
trait InternalRepo {
type Row<'a>: RowView<'a>;
fn query_borrowed<'a>(&'a self) -> Vec<Self::Row<'a>>;
}
trait PublicRepo: Send + Sync {
fn query(&self) -> Vec<RowDto>;
}
impl<T: InternalRepo> PublicRepo for T {
fn query(&self) -> Vec<RowDto> {
self.query_borrowed()
.into_iter()
.map(|row| row.to_dto())
.collect()
}
}
Pattern 3: Static Bound Conflicts
async fn bad_resolver(&self, ctx: &Context) -> Result<&Data> {
}
async fn good_resolver(&self, ctx: &Context) -> Result<DataDto> {
let borrowed = self.repo.query().await?;
Ok(borrowed.to_owned_dto())
}
async fn shared_resolver(&self) -> Result<Arc<Data>> {
Ok(Arc::clone(&self.cached_data))
}
Pattern 4: Lifetime Elision Edge Cases
struct Parser<'a> {
input: &'a str,
}
impl<'a> Parser<'a> {
fn parse(&self) -> Result<&str, Error> {
}
}
impl<'a> Parser<'a> {
fn parse<'b>(&'b self) -> Result<&'a str, Error> {
Ok(&self.input[..10])
}
}
Pattern 5: Async + Lifetime Conflicts
async fn bad_async() {
let data = get_data();
let borrowed = &data.field;
some_async_call().await;
use_borrowed(borrowed);
}
async fn good_async_clone() {
let data = get_data();
let owned = data.field.clone();
some_async_call().await;
use_owned(&owned);
}
async fn good_async_scope() {
let data = get_data();
let value = {
let borrowed = &data.field;
extract_value(borrowed)
};
some_async_call().await;
}
Common Conflict Patterns
| Pattern | Cause | Solution |
|---|
| HRTB โ dyn | Concrete vs universal lifetime | Use generic functions |
| GAT โ dyn | Variable-sized associated types | Layered design with owned DTOs |
| 'static + borrow | Lifetime contradiction | Return owned data |
| Async + borrow | Future holds state across await | Clone or drop before await |
| Closure capture + Send | Lifetime issues | Use 'static or Arc |
When to Give Up Borrowing
Performance vs Maintainability
fn should_use_owned() -> bool {
true
}
Rule of Thumb
- API layer: Default to owned data
- Internal impl: Borrow when beneficial
- Performance hotspot: Profile first, then optimize
- High complexity: Fall back to owned
Workflow
Step 1: Diagnose Error
Common errors:
"one type is more general" โ HRTB + dyn conflict
"lifetime may not live long enough" โ Borrow exceeds scope
"cannot be made into object" โ GAT or HRTB in trait
"does not live long enough" โ Early drop
Step 2: Choose Strategy
Options:
โ Simplify: Remove abstraction
โ Split: Separate borrowed/owned layers
โ Clone: Accept allocation cost
โ Arc: Shared ownership
โ Redesign: Change data flow
Step 3: Validate Solution
Check:
โ Compiles without hacky workarounds
โ Reasonable complexity
โ Performance acceptable
โ Maintainable long-term
Debugging Techniques
Minimize
Explicit Lifetimes
fn explicit<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
x
}
Accept Reality
Review Checklist
When dealing with complex lifetimes:
Verification Commands
cargo check
cargo expand
cargo clippy
Related Skills
- rust-ownership - Basic lifetime fundamentals
- rust-async - Async lifetime patterns
- rust-type-driven - Type-level design
- rust-trait - Trait object constraints
- rust-performance - When to optimize with borrowing
Localized Reference
- Chinese version: SKILL_ZH.md - ๅฎๆดไธญๆ็ๆฌ๏ผๅ
ๅซๆๆๅ
ๅฎน