diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs index b5bc9d3599acb..69dada98dc3b5 100644 --- a/compiler/rustc_typeck/src/check/method/prelude2021.rs +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -239,47 +239,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id()); let trait_generics = self.tcx.generics_of(pick.item.container.id()); - let parameter_count = trait_generics.count() - (trait_generics.has_self as usize); - let trait_name = if parameter_count == 0 { - trait_path - } else { - format!( - "{}<{}>", - trait_path, - std::iter::repeat("_").take(parameter_count).collect::>().join(", ") - ) - }; + let trait_name = + if trait_generics.params.len() <= trait_generics.has_self as usize { + trait_path + } else { + let counts = trait_generics.own_counts(); + format!( + "{}<{}>", + trait_path, + std::iter::repeat("'_") + .take(counts.lifetimes) + .chain(std::iter::repeat("_").take( + counts.types + counts.consts - trait_generics.has_self as usize + )) + .collect::>() + .join(", ") + ) + }; let mut lint = lint.build(&format!( "trait-associated function `{}` will become ambiguous in Rust 2021", method_name.name )); - let self_ty_name = self + let mut 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() - }; + // 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`. + if !self_ty_name.contains('<') { + if let Adt(def, _) = self_ty.kind() { + let generics = self.tcx.generics_of(def.did); + if !generics.params.is_empty() { + let counts = generics.own_counts(); + self_ty_name += &format!( + "<{}>", + std::iter::repeat("'_") + .take(counts.lifetimes) + .chain(std::iter::repeat("_").take(counts.types + counts.consts)) + .collect::>() + .join(", ") + ); + } + } + } lint.span_suggestion( span, "disambiguate the associated function", - format!( - "<{}{} as {}>::{}", - self_ty_name, self_ty_generics, trait_name, method_name.name, - ), + format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,), Applicability::MachineApplicable, ); diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.fixed b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.fixed new file mode 100644 index 0000000000000..a1b6f5b16baf8 --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.fixed @@ -0,0 +1,30 @@ +// See https://github.com/rust-lang/rust/issues/88470 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +pub trait PyTryFrom<'v, T>: Sized { + fn try_from(value: V) -> Result<&'v Self, T>; +} + +pub trait PyTryInto: Sized { + fn try_into(&self) -> Result<&T, i32>; +} + +struct Foo; + +impl PyTryInto for Foo +where + U: for<'v> PyTryFrom<'v, i32>, +{ + fn try_into(&self) -> Result<&U, i32> { + >::try_from(self) + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + } +} + +fn main() {} diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.rs b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.rs new file mode 100644 index 0000000000000..142ba552002fc --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.rs @@ -0,0 +1,30 @@ +// See https://github.com/rust-lang/rust/issues/88470 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +pub trait PyTryFrom<'v, T>: Sized { + fn try_from(value: V) -> Result<&'v Self, T>; +} + +pub trait PyTryInto: Sized { + fn try_into(&self) -> Result<&T, i32>; +} + +struct Foo; + +impl PyTryInto for Foo +where + U: for<'v> PyTryFrom<'v, i32>, +{ + fn try_into(&self) -> Result<&U, i32> { + U::try_from(self) + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + } +} + +fn main() {} diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr new file mode 100644 index 0000000000000..14ad9b017b694 --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr @@ -0,0 +1,16 @@ +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic-trait.rs:24:9 + | +LL | U::try_from(self) + | ^^^^^^^^^^^ help: disambiguate the associated function: `>::try_from` + | +note: the lint level is defined here + --> $DIR/future-prelude-collision-generic-trait.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 + +warning: 1 warning emitted + diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic.fixed b/src/test/ui/rust-2021/future-prelude-collision-generic.fixed index f0d8cb944cf84..1bb9ba3777404 100644 --- a/src/test/ui/rust-2021/future-prelude-collision-generic.fixed +++ b/src/test/ui/rust-2021/future-prelude-collision-generic.fixed @@ -6,32 +6,32 @@ #![allow(dead_code)] #![allow(unused_imports)] -struct Generic(T, U); +struct Generic<'a, U>(&'a U); trait MyFromIter { fn from_iter(_: i32) -> Self; } -impl MyFromIter for Generic { - fn from_iter(x: i32) -> Self { - Self(x, x) +impl MyFromIter for Generic<'static, i32> { + fn from_iter(_: i32) -> Self { + todo!() } } -impl std::iter::FromIterator for Generic { +impl std::iter::FromIterator for Generic<'static, i32> { fn from_iter>(_: T) -> Self { todo!() } } fn main() { - as MyFromIter>::from_iter(1); + 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); + 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); + 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 index 1984053705984..d7f8affc61ade 100644 --- a/src/test/ui/rust-2021/future-prelude-collision-generic.rs +++ b/src/test/ui/rust-2021/future-prelude-collision-generic.rs @@ -6,19 +6,19 @@ #![allow(dead_code)] #![allow(unused_imports)] -struct Generic(T, U); +struct Generic<'a, U>(&'a U); trait MyFromIter { fn from_iter(_: i32) -> Self; } -impl MyFromIter for Generic { - fn from_iter(x: i32) -> Self { - Self(x, x) +impl MyFromIter for Generic<'static, i32> { + fn from_iter(_: i32) -> Self { + todo!() } } -impl std::iter::FromIterator for Generic { +impl std::iter::FromIterator for Generic<'static, i32> { fn from_iter>(_: T) -> Self { todo!() } @@ -28,10 +28,10 @@ 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); + Generic::<'static, i32>::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); + 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 index 0a722baa185cd..e1d3f3c0a4629 100644 --- a/src/test/ui/rust-2021/future-prelude-collision-generic.stderr +++ b/src/test/ui/rust-2021/future-prelude-collision-generic.stderr @@ -2,7 +2,7 @@ warning: trait-associated function `from_iter` will become ambiguous in Rust 202 --> $DIR/future-prelude-collision-generic.rs:28:5 | LL | Generic::from_iter(1); - | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` | note: the lint level is defined here --> $DIR/future-prelude-collision-generic.rs:5:9 @@ -15,8 +15,8 @@ LL | #![warn(rust_2021_prelude_collisions)] 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` +LL | Generic::<'static, i32>::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 @@ -24,8 +24,8 @@ LL | Generic::::from_iter(1); 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` +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