Hi Curtis. Good point. That section of the pitch is not clear. When we update and repitch this, we should add a couple of points.
First, any declaration with an explicit lifetime dependency should generally override all the inferrence rules that would normally apply to that declaration. This should handle your case:
@lifetime(item)
func foo<T: ~Escapable, U: ~Escapable, R: ~Escapable>(
item: some BorrowedMember<T, R>,
x: T,
y: U
) -> R { … }
We currently use @lifetime
annotations instead of dependsOn
within the language implementation. That makes it easier to see where the experimental feature is used. Note that same-type inferrence is not implemented yet.
The above @lifetime
annotation would only be allowed if the compiler can recognize that BorrowedMember<T, R>
is conditionally ~Escapable
when T
is ~Escapable.
Second, same-type inferrence is limitted by the same-type requirements of the declaration's generic context. So, by itself, this function has no inferred dependencies and would in fact be an illegal declaration:
func foo<T: ~Escapable, U: ~Escapable, R: ~Escapable>(x: T, y: U) -> R { ... }
Simply calling the function with substitutions of the same type would not cause any dependency to be inferred:
func bar<T: ~Escapable>(x: T, y: T) -> T {
foo(x, y) // ERROR: no lifetime dependency
}
Instead, inferrence only happens when the declaration's generic context has same-type requirements:
struct Foo<T: ~Escapable, U: ~Escapable, R: ~Escapable> {}
extension Foo where T == R {
/* Infers @lifetime(x) */
func foo<T: ~Escapable, U: ~Escapable, R: ~Escapable>(x: T, y: U) -> R { ... }
}