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

fix-hidden-lifetime-bug-proc_macros

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

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日

#936Proc宏

Download history 15056/week @ 2024-04-21 17028/week @ 2024-04-28 14411/week @ 2024-05-05 14487/week @ 2024-05-12 13791/week @ 2024-05-19 18923/week @ 2024-05-26 77972/week @ 2024-06-02 87593/week @ 2024-06-09 90037/week @ 2024-06-16 130223/week @ 2024-06-23 106738/week @ 2024-06-30 92409/week @ 2024-07-07 90453/week @ 2024-07-14 90969/week @ 2024-07-21 98369/week @ 2024-07-28 81323/week @ 2024-08-04

每月 365,258 次下载
29 个crate中使用(通过 fix-hidden-lifetime-bug

许可协议:Zlib OR MIT OR Apache-2.0 和可能 LGPL-3.0-or-later

35KB
600

::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"]
    

    然后可以向特定的 #[fix_hidden_lifetime_bug] 注解提供 showme 参数,如下所示

    #[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–12MB
~113K SLoC