about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2021-08-31 10:41:27 +0200
committerGitHub <noreply@github.com>2021-08-31 10:41:27 +0200
commitfdf9c09c5085801b197b86e2d90b11150a952b9c (patch)
treec7ae660b64d9e89dc855b5133bc01ac0c24edd5c
parent4adacfd43e141b4a90c1d6c041e77db314eb7b42 (diff)
parent78a7d1c652149c08cc60d3a91dabb66f41807d28 (diff)
downloadrust-fdf9c09c5085801b197b86e2d90b11150a952b9c.tar.gz
rust-fdf9c09c5085801b197b86e2d90b11150a952b9c.zip
Rollup merge of #88496 - m-ou-se:prelude-collision-lifetime-generics, r=petrochenkov
Fix prelude collision lint suggestion for generics with lifetimes

Fixes https://github.com/rust-lang/rust/issues/88470

cc `@nikomatsakis`
-rw-r--r--compiler/rustc_typeck/src/check/method/prelude2021.rs65
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic-trait.fixed30
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic-trait.rs30
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr16
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic.fixed16
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic.rs14
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic.stderr10
7 files changed, 134 insertions, 47 deletions
diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs
index b5bc9d3599a..69dada98dc3 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::<Vec<_>>().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::<Vec<_>>()
+                            .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::<Vec<_>>()
+                                .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 00000000000..a1b6f5b16ba
--- /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<V>(value: V) -> Result<&'v Self, T>;
+}
+
+pub trait PyTryInto<T>: Sized {
+    fn try_into(&self) -> Result<&T, i32>;
+}
+
+struct Foo;
+
+impl<U> PyTryInto<U> for Foo
+where
+    U: for<'v> PyTryFrom<'v, i32>,
+{
+    fn try_into(&self) -> Result<&U, i32> {
+        <U as PyTryFrom<'_, _>>::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 00000000000..142ba552002
--- /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<V>(value: V) -> Result<&'v Self, T>;
+}
+
+pub trait PyTryInto<T>: Sized {
+    fn try_into(&self) -> Result<&T, i32>;
+}
+
+struct Foo;
+
+impl<U> PyTryInto<U> 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 00000000000..14ad9b017b6
--- /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: `<U as PyTryFrom<'_, _>>::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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
+
+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 f0d8cb944cf..1bb9ba37774 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>(T, U);
+struct Generic<'a, U>(&'a U);
 
 trait MyFromIter {
     fn from_iter(_: i32) -> Self;
 }
 
-impl MyFromIter for Generic<i32, i32> {
-    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<i32> for Generic<i32, i32> {
+impl std::iter::FromIterator<i32> for Generic<'static, i32> {
     fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
         todo!()
     }
 }
 
 fn main() {
-    <Generic<_, _> as MyFromIter>::from_iter(1);
+    <Generic<'_, _> 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)
-    <Generic::<i32, i32> as MyFromIter>::from_iter(1);
+    <Generic::<'static, i32> 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)
-    <Generic::<_, _> as MyFromIter>::from_iter(1);
+    <Generic::<'_, _> 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 19840537059..d7f8affc61a 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>(T, U);
+struct Generic<'a, U>(&'a U);
 
 trait MyFromIter {
     fn from_iter(_: i32) -> Self;
 }
 
-impl MyFromIter for Generic<i32, i32> {
-    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<i32> for Generic<i32, i32> {
+impl std::iter::FromIterator<i32> for Generic<'static, i32> {
     fn from_iter<T: IntoIterator<Item = i32>>(_: 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::<i32, i32>::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 0a722baa185..e1d3f3c0a46 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: `<Generic<_, _> as MyFromIter>::from_iter`
+   |     ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<'_, _> 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::<i32, i32>::from_iter(1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
+LL |     Generic::<'static, i32>::from_iter(1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<'static, i32> 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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
@@ -24,8 +24,8 @@ LL |     Generic::<i32, i32>::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: `<Generic::<_, _> as MyFromIter>::from_iter`
+LL |     Generic::<'_, _>::from_iter(1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<'_, _> 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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>