about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2023-05-23 00:32:18 +0530
committerGitHub <noreply@github.com>2023-05-23 00:32:18 +0530
commitdf8b0dfc277e302882d5052e20b7eb7b725d2bdf (patch)
tree74c14e69f9c3cb06f5cf38fe36c2577382c5fb45
parent47fe1a3e1f625f0e15baeb742e476977de26e6f3 (diff)
parent83930ecdea7eee3191316770071cc6e5019a8e3e (diff)
downloadrust-df8b0dfc277e302882d5052e20b7eb7b725d2bdf.tar.gz
rust-df8b0dfc277e302882d5052e20b7eb7b725d2bdf.zip
Rollup merge of #111612 - ChayimFriedman2:collect-into-slice-ref, r=petrochenkov
Give better error when collecting into `&[T]`

The detection of slice reference of `{integral}` in `rustc_on_unimplemented` is hacky, but a proper solution requires changing `FmtPrinter` to add a parameter to print integers as `{integral}` and I didn't want to change it just for `rustc_on_unimplemented`. I can do that if requested, though.

I'm open to better wording; this is the best I could come up with.
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs8
-rw-r--r--library/core/src/iter/traits/collect.rs10
-rw-r--r--tests/ui/iterators/collect-into-slice.rs6
-rw-r--r--tests/ui/iterators/collect-into-slice.stderr12
4 files changed, 35 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 88525e1b720..10bd027b684 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -306,6 +306,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
                 }
             }
+
+            // `&[{integral}]` - `FromIterator` needs that.
+            if let ty::Ref(_, ref_ty, rustc_ast::Mutability::Not) = self_ty.kind()
+                && let ty::Slice(sty) = ref_ty.kind()
+                && sty.is_integral()
+            {
+                flags.push((sym::_Self, Some("&[{integral}]".to_owned())));
+            }
         });
 
         if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 76b3a32880d..0675e56358f 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -95,6 +95,16 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
+        _Self = "&[{A}]",
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
+        all(A = "{integer}", any(_Self = "&[{integral}]",)),
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
         _Self = "[{A}]",
         message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size",
         label = "try explicitly collecting into a `Vec<{A}>`",
diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs
index 5a8aacb1a6d..045d40a6f71 100644
--- a/tests/ui/iterators/collect-into-slice.rs
+++ b/tests/ui/iterators/collect-into-slice.rs
@@ -14,4 +14,10 @@ fn main() {
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
     process_slice(&some_generated_vec);
+
+    let some_generated_vec = (0..10).collect();
+    //~^ ERROR a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+    //~| NOTE try explicitly collecting into a `Vec<{integer}>`
+    //~| NOTE required by a bound in `collect`
+    process_slice(some_generated_vec);
 }
diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr
index 29fff8c51c6..07dc561f06a 100644
--- a/tests/ui/iterators/collect-into-slice.stderr
+++ b/tests/ui/iterators/collect-into-slice.stderr
@@ -28,6 +28,16 @@ LL |     let some_generated_vec = (0..10).collect();
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+  --> $DIR/collect-into-slice.rs:18:38
+   |
+LL |     let some_generated_vec = (0..10).collect();
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
+   |
+   = help: the trait `FromIterator<{integer}>` is not implemented for `&[i32]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.