diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 1d58dce..d304666 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -13,6 +13,7 @@
- [“变长参数”函数与回调](./dcl/variadic.md)
- [non-lexical lifetimes (NLL)]()
- [Subtyping and Variance](./subtyping.md)
+ - [当 `&'a Ty<'a>` 变成永远借用](./variance/covariance-borrow-forever.md)
- [官方论坛帖子整理](./forum.md)
- [从同质 variants 取同类型数据](./forum/homo-variant.md)
- [常量泛型参数的分类实现](./forum/impl-const-param.md)
diff --git a/src/variance/covariance-borrow-forever.md b/src/variance/covariance-borrow-forever.md
new file mode 100644
index 0000000..0e92bad
--- /dev/null
+++ b/src/variance/covariance-borrow-forever.md
@@ -0,0 +1,380 @@
+# 当 `&'a Type<'a>` 变成了永远借用
+
+对生命周期有足够了结的 Rustancean 不会对以下代码感到不解。
+
+```rust
+struct Person<'a> {
+ name: &'a str,
+}
+
+impl<'a> Person<'a> {
+ // vvvvvvvv `&'a Person<'a>`
+ fn borrow(&'a self) -> &'a str {
+ self.name
+ }
+
+ // vvvvvvvvvvvv `&'a mut Person<'a>`
+ fn borrow_forever(&'a mut self) -> &'a str {
+ self.name
+ }
+}
+
+fn fails(mut person: Person<'_>) {
+ person.borrow_forever();
+}// error: `person` dropped here while still borrowed
+
+fn works(mut person: Person<'_>) {
+ let _one = person.borrow();
+ let _two = person.borrow();
+ &mut person; // ok
+}
+```
+
+# `&'a mut Ty<'a>` 是一种反模式
+
+你绝不应该写 `&'a mut Ty<'a>`,因为它代表永远借用自己 —— 被借用的对象活 `'a` 那么长,而你指定了借用必须活 `'a`。
+
+每当看到类似这种标注,都应该警惕这基本上是一个死胡同。因为一旦你获得 `&'a mut Ty<'a>`,那么面临两种选择
+1. 一直使用它,但它是 `Ty<'a>` 的全周期独占引用, `Ty<'a>` 活多长,这个独占引用就维持多长,借用规则让你永远不允许
+ reborrow (`&'another mut Ty<'a>`),也永远不允许有共享引用 (`&'another Ty<'a>`)。
+2. 不再使用它,那么 `&'a mut Ty<'a>` 的 `'a` 不再存活,也就是 `Ty<'a>` 不再存活,即无法再使用 `Ty<'a>`。
+
+所以,`&'a mut Ty<'a>` 这个独占引用变成对 `Ty<'a>` 的永久独占访问,似乎 `Ty<'a>` 的所有权也随着这个独占引用被夺走了:
+你永远无法得到 `Ty<'a>` 的所有权,也永远无法转移 `Ty<'a>` 的所有权 —— 因为在 Rust 中移动一个值的前提是,这个值不被借用。
+
+你还可以读读以下链接,通过具体代码去理解:
+
+* [自引用与生命周期](https://zjp-cn.github.io/translation/lifetime/self-referential.html#%E4%B8%80%E7%A7%8D%E5%8F%AF%E8%A1%8C%E4%BD%86%E6%97%A0%E7%94%A8%E5%81%9A%E6%B3%95)
+* [Borrowing something forever](https://quinedot.github.io/rust-learning/pf-borrow-forever.html)
+
+# `&'a Ty<'a>` 通常不会牵绊住你
+
+这得益于 covariance(协变),也就是生命周期可以缩短的能力。具体来说,因为 `&'a T` 具有两处协变:
+* `&` 对 `T` 是协变的,即 `&T` 可以当作 `&U` 去使用,只要 `T` 是 `U` 的子类型
+* `&` 对 `'a` 是协变的,即 `&'a` 可以当作 `&'b` 去使用,只要 `'a: 'b`[^outlive](`'a` 是 `'b` 的子类型)
+
+所以**如果 `Ty<'a>` 对 `'a` 也是协变的话**[^subtype], `&'a Ty<'a>` 可以先对 `Ty` 缩短成 `&'a Ty<'b>`,然后对 `'a`
+缩短成 `&'b Ty<'b>`,从而每次使用 `&'a Ty<'a>`,都变成了临时的借用 `&'b Ty<'b>`,最终避免了永远借用 `'a`。
+
+[^outlive]: `'a: 'b` 指 `'a` outlives `'b`,也就是 `'a` 至少和 `'b` 一样长,也就是 `'a` 活得和 `'b` 一样或者更长
+
+[^subtype]: 对于上述 `'a: 'b`,有`Ty<'a>: Ty<'b>`,即 `Ty<'a>` 是 `Ty<'b>` 的子类型。注意:严格来说,对生命周期使用
+`:` 记号是符合 Rust 的,但对类型使用 `:` 记号(`T: U`),是不太规范的。
+
+如果你对 Rust 中的 subtyping 和 variance 不熟悉,请阅读:
+* [Nomicon: subtyping](https://doc.rust-lang.org/nomicon/subtyping.html)
+* [我的笔记](https://zjp-cn.github.io/rust-note/subtyping.html)
+
+
+# 当 `&'a Ty<'a>` 牵绊你的时候
+
+可以通过破坏 `&'a Ty<'a>` 进行协变的前提,来让 `&'a Ty<'a>` 绊倒你。
+
+具体来说,如果 `Ty<'a>` 对 `'a` 不再是协变,而是不变 (invariant),那么对于 `'a: 'b`
+* `&'a Ty<'a>` 依然可以缩短成 `&'b Ty<'a>`
+* 只是 `Ty<'a>` 无法缩短成 `Ty<'b>`,从而 `&'a Ty<'a>` 和 `&'b Ty<'a>` 无法缩短成 `&'b Ty<'b>`
+
+很多情况下,这不会造成什么问题,因为你依然可以缩短生命周期得到临时的 `&'b Ty<'a>`,避免了永久借用。
+
+但随着代码变得复杂,你可能在不知不觉中重蹈 `&'a mut Ty<'a>` 的覆辙。考虑以下代码:
+
+```rust,editable
+fn main() {
+ let val = ();
+ let mut ref_val = &val;
+ let mut invariant = Invariant(&mut ref_val);
+ invariant.borrow(); // Invariant<'a>::borrow(&'a Self)
+ invariant.borrow(); // ok: 你总是可以有多个 &'a T
+
+ // 但你不能做以下事情中的任何一件
+
+ // 但不能有 &'a mut T 和 &'a T 同时存在
+ &mut invariant; // error: cannot borrow `invariant` as mutable because it is also borrowed as immutable
+
+ // 没法 move:因为 move 一个变量的前提是这个变量不被借用
+ let _move = invariant; // error: cannot move out of `invariant` because it is borrowed
+
+ // 没法显式调用 drop(和按值方式接收参数的函数):理由同“没法 move”
+ invariant.consume();
+ drop(invariant); // error: cannot move out of `invariant` because it is borrowed
+}
+
+struct Invariant<'a>(*mut &'a ()); // `*mut T` 中,`*mut` 对 T 不变
+impl<'a> Invariant<'a> {
+ fn borrow(&'a self) {}
+ fn consume(self) {}
+}
+```
+
+# 附录:永远借用会如何绊住你的脚
+
+## 与 drop check 交互
+
+```rust
+struct Invariant<'a>(*mut &'a ()); // 自身及其内部无需 Drop
+impl<'a> Invariant<'a> { fn borrow(&'a self) {} }
+
+// 在函数内创建无 Drop 的 Invariant 并永远借用
+// (这可能是你写 Rust 的第一步,代码示例成功编译)
+fn ok() {
+ let val = ();
+ let mut ref_val = &val;
+ let mut invariant = Invariant(&mut ref_val);
+
+ invariant.borrow();
+}
+// 你以为这样就没问题?看下面 fail 的情况
+
+// (你想对一段代码进行封装,却发现无法编译)
+// 将所有权移入函数(在函数外创建 Invariant),并在函数内永远借用
+// error: `val` does not live long enough
+fn fail(val: Invariant<'_>) {
+ val.borrow();
+} // `val` dropped here while still borrowed
+```
+
+
+ 当 Invariant 自身或者内部需要 Drop 时,原本无 Drop 时能通过的代码,现在无法通过。
+
+```rust
+// 原本无 Drop 时能通过的代码,现在无法通过
+// error: `invariant` does not live long enough
+fn fail() {
+ let val = ();
+ let mut ref_val = &val;
+ let mut invariant = Invariant(&mut ref_val);
+
+ invariant.borrow();
+} // `invariant` dropped here while still borrowed
+// borrow might be used here, when `invariant` is dropped and
+// runs the `Drop` code for type `Invariant`
+
+struct Invariant<'a>(*mut &'a ());
+impl<'a> Invariant<'a> { fn borrow(&'a self) {} }
+
+// 当 Invariant 自身需要 Drop
+impl Drop for Invariant<'_> { fn drop(&mut self) {} }
+```
+
+```rust
+// 原本无 Drop 时能通过的代码,现在无法通过
+// error: `invariant` does not live long enough
+fn fail() {
+ let val = ();
+ let mut ref_val = &val;
+ let invariant = Invariant(Inner(&mut ref_val));
+ invariant.borrow();
+} // 同 `当 Invariant 自身需要 Drop`
+
+struct Invariant<'a>(Inner<'a>);
+impl<'a> Invariant<'a> {
+ fn borrow(&'a self) {}
+}
+
+// 当 Invariant 内部需要 Drop
+struct Inner<'a>(*mut &'a ());
+impl Drop for Inner<'_> { fn drop(&mut self) {} }
+```
+
+对这些情况的解释见 [Nomicon: drop check](https://doc.rust-lang.org/nomicon/dropck.html)。
+
+
+
+## 与生命周期标注交互
+
+有时,你的代码没有出现显式的 `&'a Ty<'a>`,但依然有可能因为生命周期标注,让你隐式得到它。
+
+正如前述所言,`&'a Ty<'a>` 在 `Ty<'a>` 对 `'a` 协变时,通常不会造成影响;但若对 `'a` 不变,
+`&'a Ty<'a>` 与 `&'a mut Ty<'a>` 几乎造成同样的困难(唯一区别在于,一个是永久共享借用,另一个是永久独占借用)。
+
+永久借用意味着
+* `Ty<'a>` 与这个永久借用生死与共:要么一起存活,要么一起死亡
+* `Ty<'a>` 这个值一直被借用:所有权无法被获得和转移
+
+在下述例子中,代码没有显式的 `&'a Ty<'a>` 或 `&'a mut Ty<'a>` (严格来说,其实存在 `&'a mut Ty<'a>`,因为
+`&'a mut dyn std::fmt::Debug` 其实是 `&'a mut dyn ('a + std::fmt::Debug)` 的语法糖,但在这不是重点)。
+
+```rust,editable
+use std::cell::RefCell;
+fn main() {
+ let mut s1 = String::from("");
+ let mut ss = &mut s1;
+ let mut x = MyData(RefCell::new(&mut ss));
+ let y = f(&x, &x);
+ g(y, &x);
+
+ &x; // ok
+ // &mut x; // error: cannot borrow `x` as mutable because it is also borrowed as immutable
+ // drop(x);// error: cannot move out of `x` because it is borrowed
+}
+
+struct MyData<'a>(RefCell<&'a mut dyn std::fmt::Debug>);
+
+fn static_data<'any>() -> MyData<'any> {
+ MyData(RefCell::new(Box::leak(Box::new(""))))
+}
+fn f<'a, 'b>(_: &'b MyData<'a>, _: &'b MyData<'a>) -> MyData<'b> {
+ static_data()
+}
+fn g<'a, 'b>(_: MyData<'a>, _: &'b MyData<'a>) -> MyData<'b> {
+ static_data()
+}
+```
+
+但实际上是存在一个隐式的 `&'a Ty<'a>`,且 `Ty<'a>` 对 `'a` 不变,从而遇到与
+[“当 &'a Ty<'a> 牵绊你的时候”](#当-a-tya-牵绊你的时候) 相同麻烦。
+
+我自己推导生命周期会遵循一个套路,而第一步就是脱糖。f 和 g 两个函数的脱糖形式我已经写出来了,但它们的原型
+[在这](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=497b781639a77c058ec2075fa4568b0f),来自这个
+[帖子](https://rustcc.cn/article?id=431b5cac-51db-470e-ba17-3f29344eb672)。(我知道帖子给的代码不是 Rust
+惯用的代码,到处滥用了重置运算符和内存泄露,但这里的重点在于生命周期与型变,只需要看签名)
+
+核心要点是每个方法调用变成最纯粹的形式,生命周期关系写得越清楚越好。我不会在这里描述具体怎么脱糖,这不是重点。
+
+方法脱糖成函数也仅仅是个开始,接下来需要精简核心问题的代码。上面的代码已经是最能复现问题的精简版,具体过程也不是重点,无需赘述。
+
+然后,一个核心步骤是,机械地写下源代码里每处相关的生命周期和类型,这基于你对生命周期有多了解。
+
+```rust,editable
+use std::cell::RefCell;
+fn main() {
+ let mut s1 = String::from("");
+ let mut ss = &mut s1; // ss: &'0 mut String
+
+ // ss => &'0 mut String => &'1 mut String (协变, '1 来自 &'1 mut ss)
+ // &'1 mut ss => &'1 mut &'1 mut String => &'1 mut dyn ('1 + Debug)
+ // x: MyData(RefCell<'&'1 mut dyn Debug>)
+ let mut x = MyData(RefCell::new(&mut ss)); // x: MyData<'1> (不变, '1 无法缩短)
+
+ let y = f(&x, &x); // f(&'2 MyData<'1>, &'2 MyData<'1>) -> MyData<'2> ('2 来自 &'2 x)
+
+ g(y, &x); // g(MyData<'2>, &'3 MyData<'1>) -> MyData<'3> (注意:这直接将 y 的类型代入)
+ // 显然 y 的类型上的生命周期与 g 的签名上的不一致:y 与 x 在类型上具有相同的生命周期。
+ // 而 x 的生命周期 '1 无法缩短,从而试着把 '2 = '1 代入,得到
+ // g(MyData<'1>, &'3 MyData<'1>) -> MyData<'3> 符合 g 的签名。
+ // 倒推 f(&'1 MyData<'1>, &'1 MyData<'1>) -> MyData<'1>,嗯,看见 &'1 MyData<'1> (即 &'1 x) 了吗,
+ // &'1 x 是一个永久借用!
+
+ drop(x);// error: cannot move out of `x` because it is borrowed
+}
+
+struct MyData<'a>(RefCell<&'a mut dyn std::fmt::Debug>);
+
+fn static_data<'any>() -> MyData<'any> {
+ MyData(RefCell::new(Box::leak(Box::new(""))))
+}
+fn f<'a, 'b>(_: &'b MyData<'a>, _: &'b MyData<'a>) -> MyData<'b> {
+ static_data()
+}
+fn g<'a, 'b>(_: MyData<'a>, _: &'b MyData<'a>) -> MyData<'b> {
+ static_data()
+}
+```
+
+而且编译器正确指明了那个永久借用发生的位置!
+
+```rust
+error[E0505]: cannot move out of `x` because it is borrowed
+ --> src/main.rs:20:10
+ |
+9 | let mut x = MyData(RefCell::new(&mut ss));
+ | ----- binding `x` declared here
+10 |
+11 | let y = f(&x, &x);
+ | -- borrow of `x` occurs here
+...
+20 | drop(x);
+ | ^
+ | |
+ | move out of `x` occurs here
+ | borrow later used here
+```
+
+
+ 关于原帖,以及我猜来自原帖的读者会有的一些疑问
+
+对原型的标注 [在这](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ba2376e9eaef0e5b2dd7305d6b259e19)(我依然简化了一些非常无关问题的代码)。
+
+疑问1:不显式调用 `drop(x)` 不就可以通过代码,需要那么麻烦去弄清楚吗?
+
+回答:这正是我在 [与 drop check 交互](#与-drop-check-交互) 写的,你需要知道这样的代码不是真正有用的。
+如果你阅读了全文,当你按照同样方式简单封装一下代码
+([playground][mydata]),就会充分理解编译器指出的问题 —— 两个 `&'1 x` 都被捕捉到了。
+
+[mydata]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=aae44ae01b5ab0940ad6688ad37513d1
+
+```rust,no_run
+fn fail(x: MyData<'_>) {
+ let y = &x + &x;
+ let _ = y + &x;
+}
+
+error[E0597]: `x` does not live long enough
+ --> src/main.rs:71:13
+ |
+70 | fn fail(x: MyData<'_>) {
+ | -
+ | |
+ | binding `x` declared here
+ | has type `MyData<'1>`
+71 | let y = &x + &x;
+ | ^^-----
+ | |
+ | borrowed value does not live long enough
+ | assignment requires that `x` is borrowed for `'1`
+72 | let _ = y + &x;
+73 | }
+ | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+ --> src/main.rs:71:18
+ |
+70 | fn fail(x: MyData<'_>) {
+ | -
+ | |
+ | binding `x` declared here
+ | has type `MyData<'1>`
+71 | let y = &x + &x;
+ | -----^^
+ | | |
+ | | borrowed value does not live long enough
+ | assignment requires that `x` is borrowed for `'1`
+72 | let _ = y + &x;
+73 | }
+ | - `x` dropped here while still borrowed
+```
+
+疑问2:如何真正解决问题?
+
+原帖当然在滥用生命周期、滥用运算符、滥用内存泄露、滥用内部可变性,不应该那样过度设计程序。
+
+此外,`&'a Invariant<'a>` 是我们需要极力避免的,对于简化后的代码,把 f 和 g
+函数单独看签名似乎都没有过度约束,结合起来形成了过度约束。所以型变中,对于 invariance
+是最需要注意的。重新回到出错的地方,我们会注意到有一个 `'3`,它在 `&'3 MyData<'1>` 中似乎有改进的空间
+
+```rust,no_run
+ let y = f(&x, &x); // f(&'2 MyData<'1>, &'2 MyData<'1>) -> MyData<'2> ('2 来自 &'2 x)
+
+ g(y, &x); // g(MyData<'2>, &'3 MyData<'1>) -> MyData<'3> (注意:这直接将 y 的类型代入)
+```
+
+当 `'3 = '2` 时,这两行的所有 `&x` 被变成了 `&'2 x`,这是合理的,因为共享借用可以共享同一个生命周期,从而有
+([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c381fa2d1e927e20b0b42868329c9ecf))
+
+```rust,no_run
+ let y = f(&x, &x); // f(&'2 MyData<'1>, &'2 MyData<'1>) -> MyData<'2> ('2 来自 &'2 x)
+
+ g(y, &x); // g(MyData<'2>, &'2 MyData<'1>) -> MyData<'2>
+
+// 相应的 g 的签名应改为
+fn g<'a, 'b>(_: MyData<'b>, _: &'b MyData<'a>) -> MyData<'b> { ... }
+```
+
+这就是原帖中,yuyidegit 给的 [`impl<'a, 'b> Add<&'b MyData<'a>> for MyData<'b>`][yuyidegit] 能够通过编译的原因。
+
+[yuyidegit]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=56a6eba5928d4d7e2fe6bd163c7dca04
+
+
+
+
+