diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs index f13e23914f7..6eb8af98640 100644 --- a/compiler/rustc_typeck/src/check/method/prelude2021.rs +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -5,7 +5,7 @@ use rustc_ast::Mutability; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{Ref, Ty}; +use rustc_middle::ty::{Adt, Ref, Ty}; use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS; use rustc_span::symbol::kw::Underscore; use rustc_span::symbol::{sym, Ident}; @@ -255,16 +255,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method_name.name )); - let self_ty = self + let self_ty_name = self .sess() .source_map() .span_to_snippet(self_ty_span) .unwrap_or_else(|_| self_ty.to_string()); + let self_ty_generics_count = match self_ty.kind() { + // Get the number of generics the self type has (if an Adt) unless we can determine that + // the user has written the self type with generics already which we (naively) do by looking + // for a "<" in `self_ty_name`. + Adt(def, _) if !self_ty_name.contains("<") => self.tcx.generics_of(def.did).count(), + _ => 0, + }; + let self_ty_generics = if self_ty_generics_count > 0 { + format!("<{}>", vec!["_"; self_ty_generics_count].join(", ")) + } else { + String::new() + }; lint.span_suggestion( span, "disambiguate the associated function", - format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,), + format!( + "<{}{} as {}>::{}", + self_ty_name, self_ty_generics, trait_name, method_name.name, + ), Applicability::MachineApplicable, ); diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic.fixed b/src/test/ui/rust-2021/future-prelude-collision-generic.fixed new file mode 100644 index 00000000000..f0d8cb944cf --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-generic.fixed @@ -0,0 +1,37 @@ +// test for https://github.com/rust-lang/rust/issues/86940 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +struct Generic(T, U); + +trait MyFromIter { + fn from_iter(_: i32) -> Self; +} + +impl MyFromIter for Generic { + fn from_iter(x: i32) -> Self { + Self(x, x) + } +} + +impl std::iter::FromIterator for Generic { + fn from_iter>(_: T) -> Self { + todo!() + } +} + +fn main() { + as MyFromIter>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + as MyFromIter>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + as MyFromIter>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) +} diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic.rs b/src/test/ui/rust-2021/future-prelude-collision-generic.rs new file mode 100644 index 00000000000..19840537059 --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-generic.rs @@ -0,0 +1,37 @@ +// test for https://github.com/rust-lang/rust/issues/86940 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +struct Generic(T, U); + +trait MyFromIter { + fn from_iter(_: i32) -> Self; +} + +impl MyFromIter for Generic { + fn from_iter(x: i32) -> Self { + Self(x, x) + } +} + +impl std::iter::FromIterator for Generic { + fn from_iter>(_: T) -> Self { + todo!() + } +} + +fn main() { + Generic::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + Generic::::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + Generic::<_, _>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) +} diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic.stderr b/src/test/ui/rust-2021/future-prelude-collision-generic.stderr new file mode 100644 index 00000000000..2c6a63df42f --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-generic.stderr @@ -0,0 +1,34 @@ +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic.rs:28:5 + | +LL | Generic::from_iter(1); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` + | +note: the lint level is defined here + --> $DIR/future-prelude-collision-generic.rs:5:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see issue #85684 + +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic.rs:31:5 + | +LL | Generic::::from_iter(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see issue #85684 + +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic.rs:34:5 + | +LL | Generic::<_, _>::from_iter(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see issue #85684 + +warning: 3 warnings emitted + diff --git a/src/test/ui/prelude2021.rs b/src/test/ui/rust-2021/prelude2021.rs similarity index 100% rename from src/test/ui/prelude2021.rs rename to src/test/ui/rust-2021/prelude2021.rs