#生命周期 #隐藏 #实现 #bug #界限

fix-hidden-lifetime-bug

用于自动修复“在impl Trait中的隐藏生命周期”问题的proc-macro

15个版本

0.2.7 2024年8月11日
0.2.6 2024年7月17日
0.2.5 2022年7月4日
0.2.4 2021年6月29日
0.1.1 2021年5月18日

#123 in Rust模式

Download history 24714/week @ 2024-05-04 29290/week @ 2024-05-11 28421/week @ 2024-05-18 32612/week @ 2024-05-25 91296/week @ 2024-06-01 100797/week @ 2024-06-08 97780/week @ 2024-06-15 144393/week @ 2024-06-22 122311/week @ 2024-06-29 103527/week @ 2024-07-06 98118/week @ 2024-07-13 96861/week @ 2024-07-20 103604/week @ 2024-07-27 89910/week @ 2024-08-03 77406/week @ 2024-08-10 66075/week @ 2024-08-17

355,822 每月下载量
28 个crate中使用 (直接使用3个)

Zlib OR MIT OR Apache-2.0 以及可能 LGPL-3.0-or-later

23KB
84

::fix_hidden_lifetime_bug

Repository Latest version Documentation MSRV unsafe forbidden License CI

你是否遇到了以下错误(E700)之一?

  • error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
      --> examples/main.rs:13:40
       |
    13 | fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
       |                                       ^^^^^^^^^^^^^^^
       |
    note: hidden type `&'a mut &'b ()` captures the lifetime `'b` as defined on the function body at 13:12
      --> examples/main.rs:13:12
       |
    13 | fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
       |            ^^
    
    问题代码
    fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
        it
    }
    

  • error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
     --> examples/main.rs:8:45
      |
    8 | async fn bar<'a> (_: &(), _: Box<dyn Send>) {
      |                                             ^
      |
    note: hidden type `impl Future` captures lifetime smaller than the function body
     --> examples/main.rs:8:45
      |
    8 | async fn bar<'a> (_: &(), _: Box<dyn Send>) {
      |                                             ^
    
    问题代码
    async fn bar<'a> (_: &(), _: Box<dyn Send>) {
        /**/
    }
    

    编辑:从1.69.0版本开始修复


  • error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
     --> examples/main.rs:4:57
      |
    4 | async fn baz<'a>(a: &'static (), b: &(), c: &()) {
      |                                                  ^
      |
    note: hidden type `impl Future` captures lifetime smaller than the function body
     --> examples/main.rs:4:57
      |
    4 | async fn baz<'a>(a: &'static (), b: &(), c: &()) {
      |                                                  ^
    
    问题代码
    async fn baz<'a>(a: &'static (), b: &(), c: &()) {
        /**/
    }
    

    编辑:从1.69.0版本开始修复


然后你可以添加这个crate提供的属性来自动生成一个等效的签名,以使编译器不那么烦人 🙃

  • 有关更多信息,请参阅生命周期bug async 问题,以及此评论

    修复方法是执行从async fnfn的非糖化,然后只需添加必要的+ Captures<'_>界限。

  • 请参阅这篇文章,我在其中更详细地解释了问题。

用法

  1. cargo add fix_hidden_lifetime_bug,或者将以下内容添加到你的Cargo.toml文件中

    [dependencies]
    fix-hidden-lifetime-bug = "x.y.z"
    
    • 你可以使用cargo search fix_hidden_lifetime_bug来查找版本
  2. 将以下内容添加到你的lib.rs文件中

    #[macro_use]
    extern crate fix_hidden_lifetime_bug;
    
  3. 在问题函数上添加#[fix_hidden_lifetime_bug]

    #[fix_hidden_lifetime_bug] // <-- Add this!
    fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
        it
    }
    
    #[fix_hidden_lifetime_bug] // <-- Add this!
    async fn baz<'a>(fst: &'static str, snd: &str, thrd: &str) {
        /**/
    }
    

额外功能

  • 方法的全支持

    在方法的情况下,Self类型可能在其自身中隐藏生命周期参数,在这种情况下,仅对方法进行宏注解可能不足以生成修复所需的足够语法信息

    use ::fix_hidden_lifetime_bug::fix_hidden_lifetime_bug;
    
    struct Invariant<'lt> (
        fn(&()) -> &mut &'lt (),
    );
    
    impl Invariant<'_> {
        #[fix_hidden_lifetime_bug]
        fn quux(&self) -> impl '_ + Sized { self }
    }
    

    在这种情况下,还需要用属性装饰整个impl

    use ::fix_hidden_lifetime_bug::fix_hidden_lifetime_bug;
    
    struct Invariant<'lt> (
        fn(&()) -> &mut &'lt (),
    );
    
    #[fix_hidden_lifetime_bug]
    impl Invariant<'_> {
        #[fix_hidden_lifetime_bug]
        fn quux(&self) -> impl '_ + Sized { self }
    }
    

  • 显示展开

    通过启用 "showme" Cargo 功能

    [dependencies]
    fix-hidden-lifetime-bug.version = "x.y.z"
    fix-hidden-lifetime-bug.features = ["showme"]
    

    然后可以将 showme 参数传递给特定的 #[fix_hidden_lifetime_bug] 注解,如下所示

    #[fix_hidden_lifetime_bug(showme)]
    
    示例
    use ::fix_hidden_lifetime_bug::fix_hidden_lifetime_bug;
    
    #[fix_hidden_lifetime_bug(showme)]
    async fn baz<'a>(a: &'static (), b: &'_ (), c: &'_ ()) {
        println!("Hello, World!");
    }
    

    输出

    fn baz<'a, '_0, '_1, '__async_fut>(
        a: &'static (),
        b: &'_0 (),
        c: &'_1 (),
    ) -> impl '__async_fut
          + ::fix_hidden_lifetime_bug::core::future::Future<Output = ()>
          + ::fix_hidden_lifetime_bug::Captures<'a>
          + ::fix_hidden_lifetime_bug::Captures<'_0>
          + ::fix_hidden_lifetime_bug::Captures<'_1>
    where
        &'static (): '__async_fut,
        &'_0 (): '__async_fut,
        &'_1 (): '__async_fut,
    {
        async move {
            "Mention the input vars so that they get captured by the Future";
            let (a, b, c) = (a, b, c);
            println!("Hello, World!");
        }
    }
    

    这将使属性显示其展开的结果(以及其展开结果!因此输出的可读性远高于 cargo expand 或其他此类工具的输出),基本上展示了如果你愿意,如何手动修复给定的函数签名(例如,为了避免每次编译带有注解的函数时都依赖 proc-macro 处理,或者为了使 IDE 的使用更加容易)。

    如果你修复了签名,你可能还感兴趣

  • 取消选择魔法 proc-macro 属性

    如果你不想每次编译时都必须重新编译能够为你修复函数签名的 proc-macro(例如,你更希望它 显示如何修复签名,这样你就可以通过仅使用 + Captures<'> 添加来执行此操作),这样你就不必每次从头开始编译时都支付 proc-macro 编译时间,那么你可以通过禁用 crate 的 default-features 来取消选择它:这将禁用 proc-macros 功能,这是将它们带到桌面上的一项功能。

    这样,你仍然可以使用这个非常轻量级的 crate 来仅用于其 Captures<'>(以及可能 MentionsTy<>)定义,以及与其相关的文档!

    [dependencies]fix-hidden-lifetime-bug.version = "x.y.z"
    fix-hidden-lifetime-bug.default-features = false
    

依赖项

~1–11MB
~114K SLoC