Skip to content

borrowcheck error in code generated in a macro due to 2024 impl trait capture changes #132917

Closed
@ehuss

Description

@ehuss

Code generated in a proc-macro in the 2021 edition may fail to compile when used in a 2024 crate due to changes in impl trait capturing. This will leave the author of the 2024 crate without any ability to fix the issue.

Example:

// lib.rs
#[pm::pm]
pub struct S;
// proc-macro `pm`
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn pm(_attr: TokenStream, _item: TokenStream) -> TokenStream {
    "
pub struct X<'a>(::std::marker::PhantomData<&'a str>);

pub trait Tr<'a> {
    fn foo(self, x: &mut X<'a>) where Self: Sized {}
}

pub struct Y<'a>(::std::marker::PhantomData<&'a str>);

impl<'a> Tr<'a> for Y<'a> {

}

pub fn f<'a>(x: &mut X<'a>) -> impl Tr<'a> {
    Y(::std::marker::PhantomData)
}

pub fn g<'a>(x: &mut X<'a>) {
    f(x).foo(x)
}
"
    .parse()
    .unwrap()
}

When the library is migrated with cargo fix --edition, there is a warning that the proc-macro has an issue, but with no detail on what's going on (since all the code is hidden):

warning: `impl Tr<'a>` will capture more lifetimes than possibly intended in edition 2024
 --> src/lib.rs:3:1
  |
3 | #[pm::pm]
  | ^^^^^^^^^
  |
  = warning: this changes meaning in Rust 2024
  = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html>
note: specifically, this lifetime is in scope but not mentioned in the type's bounds
 --> src/lib.rs:3:1
  |
3 | #[pm::pm]
  | ^
  = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
  = note: `--force-warn impl-trait-overcaptures` implied by `--force-warn rust-2024-compatibility`
  = note: this warning originates in the attribute macro `pm::pm` (in Nightly builds, run with -Z macro-backtrace for more info)

After migrating to 2024, it fails to compile:

error[E0499]: cannot borrow `*x` as mutable more than once at a time
 --> src/lib.rs:3:1
  |
3 | #[pm::pm]
  | ^^^^^^^^^
  | |
  | `*x` was mutably borrowed here in the previous iteration of the loop
  | first borrow later used by call
  |
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
 --> src/lib.rs:3:1
  |
3 | #[pm::pm]
  | ^^^^^^^^^
  = note: this error originates in the attribute macro `pm::pm` (in Nightly builds, run with -Z macro-backtrace for more info)
help: add a precise capturing bound to avoid overcapturing
  |
3 | #[pm::pm] + use<'a>
  |           +++++++++

Additionally, the suggestion provided there is incorrect, since it is not valid syntax.

I would expect the functions generated by the proc-macro to use the capturing rules from 2021. This is an issue because editions are supposed to be independent of the crate.

Meta

rustc --version --verbose:

rustc 1.84.0-nightly (59cec72a5 2024-11-08)
binary: rustc
commit-hash: 59cec72a57af178767a7b8e7f624b06cc50f1087
commit-date: 2024-11-08
host: aarch64-apple-darwin
release: 1.84.0-nightly
LLVM version: 19.1.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-edition-2024Area: The 2024 editionC-bugCategory: This is a bug.D-editionDiagnostics: An error or lint that should account for edition differences.F-lifetime_capture_rules_2024`#![feature(lifetime_capture_rules_2024)]`L-impl_trait_overcapturesLint: impl_trait_overcaptures

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions