Rollup merge of #125889 - Nilstrieb:migrate-into-the-future, r=compiler-errors

Add migration lint for 2024 prelude additions

This adds the migration lint for the newly ambiguous methods `poll` and `into_future`. When these methods are used on types implementing the respective traits, it will be ambiguous in the future, which can lead to hard errors or behavior changes depending on the exact circumstances.

tracked by #121042

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->
r? compiler-errors as the method prober
This commit is contained in:
Matthias Krüger 2024-07-28 13:42:18 +02:00 committed by GitHub
commit cc17ca2414
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 399 additions and 1 deletions

View File

@ -9,7 +9,7 @@ use rustc_hir as hir;
use rustc_lint::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty};
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
use rustc_session::lint::builtin::{RUST_2021_PRELUDE_COLLISIONS, RUST_2024_PRELUDE_COLLISIONS};
use rustc_span::symbol::kw::{Empty, Underscore};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
@ -35,6 +35,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (prelude_or_array_lint, edition) = match segment.ident.name {
// `try_into` was added to the prelude in Rust 2021.
sym::try_into if !span.at_least_rust_2021() => (RUST_2021_PRELUDE_COLLISIONS, "2021"),
// `Future::poll` was added to the prelude in Rust 2024.
sym::poll
// We check that the self type is `Pin<&mut _>` to avoid false positives for this common name.
if !span.at_least_rust_2024()
&& let ty::Adt(adt_def, args) = self_ty.kind()
&& self.tcx.is_lang_item(adt_def.did(), hir::LangItem::Pin)
&& let ty::Ref(_, _, ty::Mutability::Mut) =
args[0].as_type().unwrap().kind() =>
{
(RUST_2024_PRELUDE_COLLISIONS, "2024")
}
// `IntoFuture::into_future` was added to the prelude in Rust 2024.
sym::into_future if !span.at_least_rust_2024() => {
(RUST_2024_PRELUDE_COLLISIONS, "2024")
}
// `into_iter` wasn't added to the prelude,
// but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter
// before Rust 2021, which results in the same problem.

View File

@ -91,6 +91,7 @@ declare_lint_pass! {
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
RUST_2021_PRELUDE_COLLISIONS,
RUST_2024_INCOMPATIBLE_PAT,
RUST_2024_PRELUDE_COLLISIONS,
SELF_CONSTRUCTOR_FROM_OUTER_ITEM,
SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
SINGLE_USE_LIFETIMES,
@ -3754,6 +3755,46 @@ declare_lint! {
};
}
declare_lint! {
/// The `rust_2024_prelude_collisions` lint detects the usage of trait methods which are ambiguous
/// with traits added to the prelude in future editions.
///
/// ### Example
///
/// ```rust,edition2021,compile_fail
/// #![deny(rust_2024_prelude_collisions)]
/// trait Meow {
/// fn poll(&self) {}
/// }
/// impl<T> Meow for T {}
///
/// fn main() {
/// core::pin::pin!(async {}).poll();
/// // ^^^^^^
/// // This call to try_into matches both Future::poll and Meow::poll as
/// // `Future` has been added to the Rust prelude in 2024 edition.
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Rust 2024, introduces two new additions to the standard library's prelude:
/// `Future` and `IntoFuture`. This results in an ambiguity as to which method/function
/// to call when an existing `poll`/`into_future` method is called via dot-call syntax or
/// a `poll`/`into_future` associated function is called directly on a type.
///
pub RUST_2024_PRELUDE_COLLISIONS,
Allow,
"detects the usage of trait methods which are ambiguous with traits added to the \
prelude in future editions",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>",
};
}
declare_lint! {
/// The `rust_2021_prefixes_incompatible_syntax` lint detects identifiers that will be parsed as a
/// prefix instead in Rust 2021.

View File

@ -0,0 +1,17 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@ check-pass
#![deny(rust_2024_prelude_collisions)]
use std::future::Future;
fn main() {
core::pin::pin!(async {}).poll(&mut context());
}
fn context() -> core::task::Context<'static> {
loop {}
}

View File

@ -0,0 +1,21 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn poll(&self, _ctx: &mut core::task::Context<'_>) {}
}
impl<T> Meow for T {}
fn main() {
Meow::poll(&core::pin::pin!(async {}), &mut context());
//[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}
fn context() -> core::task::Context<'static> {
loop {}
}

View File

@ -0,0 +1,16 @@
error: trait method `poll` will become ambiguous in Rust 2024
--> $DIR/future-poll-async-block.rs:14:5
|
LL | core::pin::pin!(async {}).poll(&mut context());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())`
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
note: the lint level is defined here
--> $DIR/future-poll-async-block.rs:8:9
|
LL | #![deny(rust_2024_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -0,0 +1,21 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn poll(&self, _ctx: &mut core::task::Context<'_>) {}
}
impl<T> Meow for T {}
fn main() {
core::pin::pin!(async {}).poll(&mut context());
//[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}
fn context() -> core::task::Context<'static> {
loop {}
}

View File

@ -0,0 +1,21 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn poll(&self) {}
}
impl<T> Meow for T {}
fn main() {
// This is a deliberate false positive.
// While `()` does not implement `Future` and can therefore not be ambiguous, we
// do not check that in the lint, as that introduces additional complexities.
// Just checking whether the self type is `Pin<&mut _>` is enough.
Meow::poll(&core::pin::pin!(()));
//[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}

View File

@ -0,0 +1,16 @@
error: trait method `poll` will become ambiguous in Rust 2024
--> $DIR/future-poll-not-future-pinned.rs:18:5
|
LL | core::pin::pin!(()).poll();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(()))`
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
note: the lint level is defined here
--> $DIR/future-poll-not-future-pinned.rs:8:9
|
LL | #![deny(rust_2024_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -0,0 +1,21 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn poll(&self) {}
}
impl<T> Meow for T {}
fn main() {
// This is a deliberate false positive.
// While `()` does not implement `Future` and can therefore not be ambiguous, we
// do not check that in the lint, as that introduces additional complexities.
// Just checking whether the self type is `Pin<&mut _>` is enough.
core::pin::pin!(()).poll();
//[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}

View File

@ -0,0 +1,15 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@ check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn poll(&self) {}
}
impl<T> Meow for T {}
fn main() {
// As the self type here is not `Pin<&mut _>`, the lint does not fire.
().poll();
}

View File

@ -0,0 +1,17 @@
//@ edition: 2021
#![deny(rust_2024_compatibility)]
trait Meow {
fn poll(&self, _ctx: &mut core::task::Context<'_>) {}
}
impl<T> Meow for T {}
fn main() {
core::pin::pin!(async {}).poll(&mut context());
//~^ ERROR trait method `poll` will become ambiguous in Rust 2024
//~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}
fn context() -> core::task::Context<'static> {
loop {}
}

View File

@ -0,0 +1,17 @@
error: trait method `poll` will become ambiguous in Rust 2024
--> $DIR/in_2024_compatibility.rs:10:5
|
LL | core::pin::pin!(async {}).poll(&mut context());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())`
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
note: the lint level is defined here
--> $DIR/in_2024_compatibility.rs:3:9
|
LL | #![deny(rust_2024_compatibility)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[deny(rust_2024_prelude_collisions)]` implied by `#[deny(rust_2024_compatibility)]`
error: aborting due to 1 previous error

View File

@ -0,0 +1,29 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn into_future(&self) {}
}
impl Meow for Cat {}
struct Cat;
impl core::future::IntoFuture for Cat {
type Output = ();
type IntoFuture = core::future::Ready<()>;
fn into_future(self) -> Self::IntoFuture {
core::future::ready(())
}
}
fn main() {
Meow::into_future(&Cat);
//[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}

View File

@ -0,0 +1,16 @@
error: trait method `into_future` will become ambiguous in Rust 2024
--> $DIR/into-future-adt.rs:26:5
|
LL | Cat.into_future();
| ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)`
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
note: the lint level is defined here
--> $DIR/into-future-adt.rs:8:9
|
LL | #![deny(rust_2024_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -0,0 +1,29 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn into_future(&self) {}
}
impl Meow for Cat {}
struct Cat;
impl core::future::IntoFuture for Cat {
type Output = ();
type IntoFuture = core::future::Ready<()>;
fn into_future(self) -> Self::IntoFuture {
core::future::ready(())
}
}
fn main() {
Cat.into_future();
//[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}

View File

@ -0,0 +1,24 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@ check-pass
#![deny(rust_2024_prelude_collisions)]
use core::future::IntoFuture;
struct Cat;
impl IntoFuture for Cat {
type Output = ();
type IntoFuture = core::future::Ready<()>;
fn into_future(self) -> Self::IntoFuture {
core::future::ready(())
}
}
fn main() {
let _ = Cat.into_future();
}

View File

@ -0,0 +1,23 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn into_future(&self) {}
}
impl Meow for Cat {}
struct Cat;
fn main() {
// This is a false positive, but it should be rare enough to not matter, and checking whether
// it implements the trait can have other nontrivial consequences, so it was decided to accept
// this.
Meow::into_future(&Cat);
//[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}

View File

@ -0,0 +1,16 @@
error: trait method `into_future` will become ambiguous in Rust 2024
--> $DIR/into-future-not-into-future.rs:20:5
|
LL | Cat.into_future();
| ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)`
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
note: the lint level is defined here
--> $DIR/into-future-not-into-future.rs:8:9
|
LL | #![deny(rust_2024_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -0,0 +1,23 @@
//@ revisions: e2021 e2024
//@[e2021] edition: 2021
//@[e2021] run-rustfix
//@[e2024] edition: 2024
//@[e2024] compile-flags: -Zunstable-options
//@[e2024] check-pass
#![deny(rust_2024_prelude_collisions)]
trait Meow {
fn into_future(&self) {}
}
impl Meow for Cat {}
struct Cat;
fn main() {
// This is a false positive, but it should be rare enough to not matter, and checking whether
// it implements the trait can have other nontrivial consequences, so it was decided to accept
// this.
Cat.into_future();
//[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
//[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
}