From d163541022248c12f166a2606cb3295986540318 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 15 Nov 2024 09:53:38 -0800 Subject: [PATCH 1/2] Add test for precise-capturing from an external macro --- .../auxiliary/no-use-macro.rs | 20 +++++ .../precise-capturing/auxiliary/no-use-pm.rs | 29 ++++++ .../precise-capturing/external-macro.rs | 29 ++++++ .../precise-capturing/external-macro.stderr | 89 +++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 tests/ui/impl-trait/precise-capturing/auxiliary/no-use-macro.rs create mode 100644 tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs create mode 100644 tests/ui/impl-trait/precise-capturing/external-macro.rs create mode 100644 tests/ui/impl-trait/precise-capturing/external-macro.stderr diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-macro.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-macro.rs new file mode 100644 index 00000000000..2efdc2342c1 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-macro.rs @@ -0,0 +1,20 @@ +// A macro_rules macro in 2015 that has an RPIT without `use<>` that would +// cause a problem with 2024 capturing rules. + +#[macro_export] +macro_rules! macro_rpit { + () => { + fn test_mbe(x: &Vec) -> impl std::fmt::Display { + x[0] + } + + pub fn from_mbe() { + let mut x = vec![]; + x.push(1); + + let element = test_mbe(&x); + x.push(2); + println!("{element}"); + } + }; +} diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs new file mode 100644 index 00000000000..e197dcfef80 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs @@ -0,0 +1,29 @@ +// A proc-macro in 2015 that has an RPIT without `use<>` that would cause a +// problem with 2024 capturing rules. + +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn pm_rpit(input: TokenStream) -> TokenStream { + "fn test_pm(x: &Vec) -> impl std::fmt::Display { + x[0] +} + +pub fn from_pm() { + let mut x = vec![]; + x.push(1); + + let element = test_pm(&x); + x.push(2); + println!(\"{element}\"); +} +" + .parse() + .unwrap() +} diff --git a/tests/ui/impl-trait/precise-capturing/external-macro.rs b/tests/ui/impl-trait/precise-capturing/external-macro.rs new file mode 100644 index 00000000000..72f72bc7b05 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/external-macro.rs @@ -0,0 +1,29 @@ +// Tests that code generated from an external macro (MBE and proc-macro) that +// has an RPIT will not fail when the call-site is 2024. +// https://github.com/rust-lang/rust/issues/132917 + +//@ aux-crate: no_use_pm=no-use-pm.rs +//@ aux-crate: no_use_macro=no-use-macro.rs +//@ edition: 2024 +//@ compile-flags:-Z unstable-options + +no_use_pm::pm_rpit!{} +//~^ ERROR: cannot borrow `x` as mutable + +no_use_macro::macro_rpit!{} +//~^ ERROR: cannot borrow `x` as mutable + +fn main() { + let mut x = vec![]; + x.push(1); + + let element = test_pm(&x); + x.push(2); + //~^ ERROR: cannot borrow `x` as mutable + println!("{element}"); + + let element = test_mbe(&x); + x.push(2); + //~^ ERROR: cannot borrow `x` as mutable + println!("{element}"); +} diff --git a/tests/ui/impl-trait/precise-capturing/external-macro.stderr b/tests/ui/impl-trait/precise-capturing/external-macro.stderr new file mode 100644 index 00000000000..88a142088dd --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/external-macro.stderr @@ -0,0 +1,89 @@ +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/external-macro.rs:10:1 + | +LL | no_use_pm::pm_rpit!{} + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | mutable borrow occurs here + | immutable borrow occurs here + | immutable borrow later used here + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/external-macro.rs:10:1 + | +LL | no_use_pm::pm_rpit!{} + | ^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `no_use_pm::pm_rpit` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | no_use_pm::pm_rpit!{} + use<> + | +++++++ + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/external-macro.rs:13:1 + | +LL | no_use_macro::macro_rpit!{} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | mutable borrow occurs here + | immutable borrow occurs here + | immutable borrow later used here + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/external-macro.rs:13:1 + | +LL | no_use_macro::macro_rpit!{} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `no_use_macro::macro_rpit` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the precise capturing `use<...>` syntax to make the captures explicit + --> $DIR/auxiliary/no-use-macro.rs:7:60 + | +LL | fn test_mbe(x: &Vec) -> impl std::fmt::Display + use<> { + | +++++++ + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/external-macro.rs:21:5 + | +LL | let element = test_pm(&x); + | -- immutable borrow occurs here +LL | x.push(2); + | ^^^^^^^^^ mutable borrow occurs here +LL | +LL | println!("{element}"); + | --------- immutable borrow later used here + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/external-macro.rs:20:19 + | +LL | let element = test_pm(&x); + | ^^^^^^^^^^^ +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | no_use_pm::pm_rpit!{} + use<> + | +++++++ + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/external-macro.rs:26:5 + | +LL | let element = test_pm(&x); + | -- immutable borrow occurs here +... +LL | x.push(2); + | ^^^^^^^^^ mutable borrow occurs here +... +LL | } + | - immutable borrow might be used here, when `element` is dropped and runs the destructor for type `impl std::fmt::Display` + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/external-macro.rs:20:19 + | +LL | let element = test_pm(&x); + | ^^^^^^^^^^^ +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | no_use_pm::pm_rpit!{} + use<> + | +++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0502`. From 03e2828e8876e9c2d2ec9238d9cdce82e7b93798 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 15 Nov 2024 10:06:53 -0800 Subject: [PATCH 2/2] Fix span edition for 2024 RPIT coming from an external macro This fixes a problem where code generated by an external macro with an RPIT would end up using the call-site edition instead of the macro's edition for the RPIT. When used from a 2024 crate, this caused the code to change behavior to the 2024 capturing rules, which we don't want. This was caused by the impl-trait lowering code would replace the span with one marked with `DesugaringKind::OpaqueTy` desugaring. However, it was also overriding the edition of the span with the edition of the local crate. Instead it should be using the edition of the span itself. Fixes https://github.com/rust-lang/rust/issues/132917 --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- .../precise-capturing/external-macro.rs | 5 +- .../precise-capturing/external-macro.stderr | 89 ------------------- 3 files changed, 2 insertions(+), 94 deletions(-) delete mode 100644 tests/ui/impl-trait/precise-capturing/external-macro.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5a0e9e8aec0..d53280751fc 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -738,7 +738,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { allow_internal_unstable: Option>, ) -> Span { self.tcx.with_stable_hashing_context(|hcx| { - span.mark_with_reason(allow_internal_unstable, reason, self.tcx.sess.edition(), hcx) + span.mark_with_reason(allow_internal_unstable, reason, span.edition(), hcx) }) } diff --git a/tests/ui/impl-trait/precise-capturing/external-macro.rs b/tests/ui/impl-trait/precise-capturing/external-macro.rs index 72f72bc7b05..492e8036461 100644 --- a/tests/ui/impl-trait/precise-capturing/external-macro.rs +++ b/tests/ui/impl-trait/precise-capturing/external-macro.rs @@ -6,12 +6,11 @@ //@ aux-crate: no_use_macro=no-use-macro.rs //@ edition: 2024 //@ compile-flags:-Z unstable-options +//@ check-pass no_use_pm::pm_rpit!{} -//~^ ERROR: cannot borrow `x` as mutable no_use_macro::macro_rpit!{} -//~^ ERROR: cannot borrow `x` as mutable fn main() { let mut x = vec![]; @@ -19,11 +18,9 @@ fn main() { let element = test_pm(&x); x.push(2); - //~^ ERROR: cannot borrow `x` as mutable println!("{element}"); let element = test_mbe(&x); x.push(2); - //~^ ERROR: cannot borrow `x` as mutable println!("{element}"); } diff --git a/tests/ui/impl-trait/precise-capturing/external-macro.stderr b/tests/ui/impl-trait/precise-capturing/external-macro.stderr deleted file mode 100644 index 88a142088dd..00000000000 --- a/tests/ui/impl-trait/precise-capturing/external-macro.stderr +++ /dev/null @@ -1,89 +0,0 @@ -error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/external-macro.rs:10:1 - | -LL | no_use_pm::pm_rpit!{} - | ^^^^^^^^^^^^^^^^^^^^^ - | | - | mutable borrow occurs here - | immutable borrow occurs here - | immutable borrow later used here - | -note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules - --> $DIR/external-macro.rs:10:1 - | -LL | no_use_pm::pm_rpit!{} - | ^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `no_use_pm::pm_rpit` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the precise capturing `use<...>` syntax to make the captures explicit - | -LL | no_use_pm::pm_rpit!{} + use<> - | +++++++ - -error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/external-macro.rs:13:1 - | -LL | no_use_macro::macro_rpit!{} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | mutable borrow occurs here - | immutable borrow occurs here - | immutable borrow later used here - | -note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules - --> $DIR/external-macro.rs:13:1 - | -LL | no_use_macro::macro_rpit!{} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `no_use_macro::macro_rpit` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the precise capturing `use<...>` syntax to make the captures explicit - --> $DIR/auxiliary/no-use-macro.rs:7:60 - | -LL | fn test_mbe(x: &Vec) -> impl std::fmt::Display + use<> { - | +++++++ - -error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/external-macro.rs:21:5 - | -LL | let element = test_pm(&x); - | -- immutable borrow occurs here -LL | x.push(2); - | ^^^^^^^^^ mutable borrow occurs here -LL | -LL | println!("{element}"); - | --------- immutable borrow later used here - | -note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules - --> $DIR/external-macro.rs:20:19 - | -LL | let element = test_pm(&x); - | ^^^^^^^^^^^ -help: use the precise capturing `use<...>` syntax to make the captures explicit - | -LL | no_use_pm::pm_rpit!{} + use<> - | +++++++ - -error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/external-macro.rs:26:5 - | -LL | let element = test_pm(&x); - | -- immutable borrow occurs here -... -LL | x.push(2); - | ^^^^^^^^^ mutable borrow occurs here -... -LL | } - | - immutable borrow might be used here, when `element` is dropped and runs the destructor for type `impl std::fmt::Display` - | -note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules - --> $DIR/external-macro.rs:20:19 - | -LL | let element = test_pm(&x); - | ^^^^^^^^^^^ -help: use the precise capturing `use<...>` syntax to make the captures explicit - | -LL | no_use_pm::pm_rpit!{} + use<> - | +++++++ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0502`.