Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add migration lint for 2024 prelude additions #125889

Merged
merged 1 commit into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand Down
41 changes: 41 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -3750,6 +3751,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>",
};
Comment on lines +3784 to +3791
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be good to add a test to demonstrate that this is picked up in the rust_2024_compatibility lint group, as in:

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, added it

}

declare_lint! {
/// The `rust_2021_prefixes_incompatible_syntax` lint detects identifiers that will be parsed as a
/// prefix instead in Rust 2021.
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs
Original file line number Diff line number Diff line change
@@ -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 {}
}
Original file line number Diff line number Diff line change
@@ -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 {}
}
Original file line number Diff line number Diff line change
@@ -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

21 changes: 21 additions & 0 deletions tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs
Original file line number Diff line number Diff line change
@@ -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 {}
}
Original file line number Diff line number Diff line change
@@ -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!
}
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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!
}
15 changes: 15 additions & 0 deletions tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs
Original file line number Diff line number Diff line change
@@ -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();
}
17 changes: 17 additions & 0 deletions tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs
Original file line number Diff line number Diff line change
@@ -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 {}
}
17 changes: 17 additions & 0 deletions tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr
Original file line number Diff line number Diff line change
@@ -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

29 changes: 29 additions & 0 deletions tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed
Original file line number Diff line number Diff line change
@@ -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!
}
16 changes: 16 additions & 0 deletions tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr
Original file line number Diff line number Diff line change
@@ -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

29 changes: 29 additions & 0 deletions tests/ui/rust-2024/prelude-migration/into-future-adt.rs
Original file line number Diff line number Diff line change
@@ -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!
}
Original file line number Diff line number Diff line change
@@ -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();
}
Loading
Loading