Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error messages when collecting into [T; n] #96466

Merged
merged 1 commit into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
32 changes: 13 additions & 19 deletions library/core/src/iter/traits/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}>`"
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/iterators/collect-into-array.rs
Original file line number Diff line number Diff line change
@@ -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`
}
16 changes: 16 additions & 0 deletions src/test/ui/iterators/collect-into-array.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion src/test/ui/iterators/collect-into-slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/iterators/collect-into-slice.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down