about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-04-26 21:09:26 -0700
committerMichael Goulet <michael@errs.io>2022-04-26 21:37:10 -0700
commit83d701e569914b9dbf7be002f62d63e790a5cb70 (patch)
tree20c1709a18e363bed2de5f137ca6e4bddb44916f
parenta7197189cd0e3a86d1b661d1dceb8bdff021d0b8 (diff)
downloadrust-83d701e569914b9dbf7be002f62d63e790a5cb70.tar.gz
rust-83d701e569914b9dbf7be002f62d63e790a5cb70.zip
Better error messages when collecting into `[T; n]`
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs42
-rw-r--r--library/core/src/iter/traits/collect.rs32
-rw-r--r--src/test/ui/iterators/collect-into-array.rs7
-rw-r--r--src/test/ui/iterators/collect-into-array.stderr16
-rw-r--r--src/test/ui/iterators/collect-into-slice.rs2
-rw-r--r--src/test/ui/iterators/collect-into-slice.stderr2
6 files changed, 69 insertions, 32 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 31b92d52beb..9e9c230aebb 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
@@ -217,22 +217,42 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 flags.push((sym::_Self, Some(shortname.to_owned())));
             }
 
+            // Slices give us `[]`, `[{ty}]`
+            if let ty::Slice(aty) = self_ty.kind() {
+                flags.push((sym::_Self, Some("[]".to_string())));
+                if let Some(def) = aty.ty_adt_def() {
+                    // We also want to be able to select the slice's type's original
+                    // signature with no type arguments resolved
+                    let type_string = self.tcx.type_of(def.did()).to_string();
+                    flags.push((sym::_Self, Some(format!("[{type_string}]"))));
+                }
+                if aty.is_integral() {
+                    flags.push((sym::_Self, Some("[{integral}]".to_string())));
+                }
+            }
+
+            // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
             if let ty::Array(aty, len) = self_ty.kind() {
-                flags.push((sym::_Self, Some("[]".to_owned())));
-                flags.push((sym::_Self, Some(format!("[{}]", aty))));
+                flags.push((sym::_Self, Some("[]".to_string())));
+                let len = len.val().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
+                flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
+                if let Some(n) = len {
+                    flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
+                }
                 if let Some(def) = aty.ty_adt_def() {
                     // We also want to be able to select the array's type's original
                     // signature with no type arguments resolved
                     let type_string = self.tcx.type_of(def.did()).to_string();
-                    flags.push((sym::_Self, Some(format!("[{}]", type_string))));
-
-                    let len =
-                        len.val().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
-                    let string = match len {
-                        Some(n) => format!("[{}; {}]", type_string, n),
-                        None => format!("[{}; _]", type_string),
-                    };
-                    flags.push((sym::_Self, Some(string)));
+                    flags.push((sym::_Self, Some(format!("[{type_string}; _]"))));
+                    if let Some(n) = len {
+                        flags.push((sym::_Self, Some(format!("[{type_string}; {n}]"))));
+                    }
+                }
+                if aty.is_integral() {
+                    flags.push((sym::_Self, Some("[{integral}; _]".to_string())));
+                    if let Some(n) = len {
+                        flags.push((sym::_Self, Some(format!("[{{integral}}; {n}]"))));
+                    }
                 }
             }
             if let ty::Dynamic(traits, _) = self_ty.kind() {
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index e6900742c31..12ca508bed2 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -96,30 +96,24 @@
 #[rustc_on_unimplemented(
     on(
         _Self = "[{A}]",
-        message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size",
+        message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size",
         label = "try explicitly collecting into a `Vec<{A}>`",
     ),
     on(
-        all(
-            A = "{integer}",
-            any(
-                _Self = "[i8]",
-                _Self = "[i16]",
-                _Self = "[i32]",
-                _Self = "[i64]",
-                _Self = "[i128]",
-                _Self = "[isize]",
-                _Self = "[u8]",
-                _Self = "[u16]",
-                _Self = "[u32]",
-                _Self = "[u64]",
-                _Self = "[u128]",
-                _Self = "[usize]"
-            )
-        ),
-        message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size",
+        all(A = "{integer}", any(_Self = "[{integral}]",)),
+        message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size",
         label = "try explicitly collecting into a `Vec<{A}>`",
     ),
+    on(
+        _Self = "[{A}; _]",
+        message = "an array of type `{Self}` cannot be built directly from an iterator",
+        label = "try collecting into a `Vec<{A}>`, then using `.try_into()`",
+    ),
+    on(
+        all(A = "{integer}", any(_Self = "[{integral}; _]",)),
+        message = "an array of type `{Self}` cannot be built directly from an iterator",
+        label = "try collecting into a `Vec<{A}>`, then using `.try_into()`",
+    ),
     message = "a value of type `{Self}` cannot be built from an iterator \
                over elements of type `{A}`",
     label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs
new file mode 100644
index 00000000000..a1144c8cb8c
--- /dev/null
+++ b/src/test/ui/iterators/collect-into-array.rs
@@ -0,0 +1,7 @@
+fn main() {
+    //~^ NOTE required by a bound in this
+    let whatever: [u32; 10] = (0..10).collect();
+    //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
+    //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
+    //~| NOTE required by a bound in `collect`
+}
diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr
new file mode 100644
index 00000000000..7be53a4873b
--- /dev/null
+++ b/src/test/ui/iterators/collect-into-array.stderr
@@ -0,0 +1,16 @@
+error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
+  --> $DIR/collect-into-array.rs:3:39
+   |
+LL |     let whatever: [u32; 10] = (0..10).collect();
+   |                                       ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
+   |
+   = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs
index 905752dec74..aafa6bc8b95 100644
--- a/src/test/ui/iterators/collect-into-slice.rs
+++ b/src/test/ui/iterators/collect-into-slice.rs
@@ -6,7 +6,7 @@ fn process_slice(data: &[i32]) {
 fn main() {
     let some_generated_vec = (0..10).collect();
     //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time
-    //~| ERROR a value of type `[i32]` cannot be built since `[i32]` has no definite size
+    //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size
     //~| NOTE try explicitly collecting into a `Vec<{integer}>`
     //~| NOTE required by a bound in `collect`
     //~| NOTE all local variables must have a statically known size
diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr
index 521f239451d..4842e65fe97 100644
--- a/src/test/ui/iterators/collect-into-slice.stderr
+++ b/src/test/ui/iterators/collect-into-slice.stderr
@@ -8,7 +8,7 @@ LL |     let some_generated_vec = (0..10).collect();
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
 
-error[E0277]: a value of type `[i32]` cannot be built since `[i32]` has no definite size
+error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
   --> $DIR/collect-into-slice.rs:7:38
    |
 LL |     let some_generated_vec = (0..10).collect();